From 2a990d69669c2a2cd16134e8ebbd2750060f8071 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 27 May 2021 16:32:35 -0700 Subject: [PATCH 01/14] stage1: rework tokenizer to match stage2 * Extracts AstGen logic from ir.cpp into astgen.cpp. Reduces the largest file of stage1 from 33,551 lines to 25,510. * tokenizer: rework it completely to match the stage2 tokenizer logic. They can now be maintained together; when one is changed, the other can be changed in the same way. - Each token now takes up 13 bytes instead of 64 bytes. The tokenizer does not parse char literals, string literals, integer literals, etc into meaningful data. Instead, that happens during parsing or astgen. - no longer store line offsets. Error messages scan source files to find the line/column as needed (same as stage2). - main loop: instead of checking the loop, handle a null byte explicitly in the switch statements. This is a nice improvement that we may want to backport to stage2. - delete some dead tokens, artifacts of past syntax that no longer exists. * Parser: fix a TODO by parsing builtin functions as tokens rather than `@` as a separate token. This is how stage2 does it. * Remove some debugging infrastructure. These will need to be redone, if at all, as the code migrates to match stage2. - remove the ast_render code. - remove the IR debugging stuff - remove teh token printing code --- CMakeLists.txt | 4 +- lib/std/zig/string_literal.zig | 1 + src/stage1.zig | 2 + src/stage1/all_types.hpp | 102 +- src/stage1/analyze.cpp | 155 +- src/stage1/analyze.hpp | 6 +- src/stage1/ast_render.cpp | 1241 ----- src/stage1/ast_render.hpp | 20 - src/stage1/astgen.cpp | 8120 +++++++++++++++++++++++++++++++ src/stage1/astgen.hpp | 43 + src/stage1/bigfloat.cpp | 3 +- src/stage1/bigfloat.hpp | 2 +- src/stage1/codegen.cpp | 44 +- src/stage1/dump_analysis.cpp | 42 +- src/stage1/errmsg.cpp | 59 +- src/stage1/errmsg.hpp | 6 +- src/stage1/error.cpp | 2 + src/stage1/ir.cpp | 8215 +------------------------------- src/stage1/ir.hpp | 7 - src/stage1/parser.cpp | 1503 +++--- src/stage1/parser.hpp | 17 +- src/stage1/stage2.h | 2 + src/stage1/tokenizer.cpp | 2189 ++++----- src/stage1/tokenizer.hpp | 72 +- test/behavior/misc.zig | 15 +- 25 files changed, 10445 insertions(+), 11427 deletions(-) delete mode 100644 src/stage1/ast_render.cpp delete mode 100644 src/stage1/ast_render.hpp create mode 100644 src/stage1/astgen.cpp create mode 100644 src/stage1/astgen.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 024a06b425..b58f714a22 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -292,7 +292,7 @@ set(ZIG0_SOURCES set(STAGE1_SOURCES "${CMAKE_SOURCE_DIR}/src/stage1/analyze.cpp" - "${CMAKE_SOURCE_DIR}/src/stage1/ast_render.cpp" + "${CMAKE_SOURCE_DIR}/src/stage1/astgen.cpp" "${CMAKE_SOURCE_DIR}/src/stage1/bigfloat.cpp" "${CMAKE_SOURCE_DIR}/src/stage1/bigint.cpp" "${CMAKE_SOURCE_DIR}/src/stage1/buffer.cpp" @@ -307,11 +307,11 @@ set(STAGE1_SOURCES "${CMAKE_SOURCE_DIR}/src/stage1/os.cpp" "${CMAKE_SOURCE_DIR}/src/stage1/parser.cpp" "${CMAKE_SOURCE_DIR}/src/stage1/range_set.cpp" + "${CMAKE_SOURCE_DIR}/src/stage1/softfloat_ext.cpp" "${CMAKE_SOURCE_DIR}/src/stage1/stage1.cpp" "${CMAKE_SOURCE_DIR}/src/stage1/target.cpp" "${CMAKE_SOURCE_DIR}/src/stage1/tokenizer.cpp" "${CMAKE_SOURCE_DIR}/src/stage1/util.cpp" - "${CMAKE_SOURCE_DIR}/src/stage1/softfloat_ext.cpp" ) set(OPTIMIZED_C_SOURCES "${CMAKE_SOURCE_DIR}/src/stage1/parse_f128.c" diff --git a/lib/std/zig/string_literal.zig b/lib/std/zig/string_literal.zig index 992affc829..b1dc53c47f 100644 --- a/lib/std/zig/string_literal.zig +++ b/lib/std/zig/string_literal.zig @@ -107,6 +107,7 @@ pub fn parseAppend(buf: *std.ArrayList(u8), bytes: []const u8) error{OutOfMemory const hex_str = slice[index + 2 .. index_end]; if (std.fmt.parseUnsigned(u32, hex_str, 16)) |uint| { if (uint <= 0x10ffff) { + // TODO this incorrectly depends on endianness try buf.appendSlice(std.mem.toBytes(uint)[0..]); state = State.Start; index = index_end; // loop-header increments diff --git a/src/stage1.zig b/src/stage1.zig index 1b7eadd1a8..f7cc6e2890 100644 --- a/src/stage1.zig +++ b/src/stage1.zig @@ -252,6 +252,8 @@ const Error = extern enum { ZigIsTheCCompiler, FileBusy, Locked, + InvalidCharacter, + UnicodePointTooLarge, }; // ABI warning diff --git a/src/stage1/all_types.hpp b/src/stage1/all_types.hpp index 88d10e9e6a..ad7a8cd5cb 100644 --- a/src/stage1/all_types.hpp +++ b/src/stage1/all_types.hpp @@ -670,7 +670,7 @@ enum NodeType { NodeTypeIntLiteral, NodeTypeStringLiteral, NodeTypeCharLiteral, - NodeTypeSymbol, + NodeTypeIdentifier, NodeTypePrefixOpExpr, NodeTypePointerType, NodeTypeFnCallExpr, @@ -710,6 +710,7 @@ enum NodeType { NodeTypeAwaitExpr, NodeTypeSuspend, NodeTypeAnyFrameType, + // main_token points to the identifier. NodeTypeEnumLiteral, NodeTypeAnyTypeField, }; @@ -733,7 +734,8 @@ struct AstNodeFnProto { AstNode *section_expr; // populated if the "callconv(S)" is present AstNode *callconv_expr; - Buf doc_comments; + + TokenIndex doc_comments; // This is set based only on the existence of a noinline or inline keyword. // This is then resolved to an is_noinline bool and (potentially .Inline) @@ -755,8 +757,8 @@ struct AstNodeFnDef { struct AstNodeParamDecl { Buf *name; AstNode *type; - Token *anytype_token; - Buf doc_comments; + TokenIndex doc_comments; + TokenIndex anytype_token; bool is_noalias; bool is_comptime; bool is_var_args; @@ -799,9 +801,9 @@ struct AstNodeVariableDeclaration { AstNode *align_expr; // populated if the "section(S)" is present AstNode *section_expr; - Token *threadlocal_tok; - Buf doc_comments; + TokenIndex doc_comments; + TokenIndex threadlocal_tok; VisibMod visib_mod; bool is_const; bool is_comptime; @@ -935,13 +937,14 @@ struct AstNodePrefixOpExpr { }; struct AstNodePointerType { - Token *star_token; + TokenIndex star_token; + TokenIndex allow_zero_token; + TokenIndex bit_offset_start; + TokenIndex host_int_bytes; + AstNode *sentinel; AstNode *align_expr; - BigInt *bit_offset_start; - BigInt *host_int_bytes; AstNode *op_expr; - Token *allow_zero_token; bool is_const; bool is_volatile; }; @@ -956,7 +959,7 @@ struct AstNodeArrayType { AstNode *sentinel; AstNode *child_type; AstNode *align_expr; - Token *allow_zero_token; + TokenIndex allow_zero_token; bool is_const; bool is_volatile; }; @@ -974,11 +977,11 @@ struct AstNodeIfBoolExpr { struct AstNodeTryExpr { Buf *var_symbol; - bool var_is_ptr; AstNode *target_node; AstNode *then_node; AstNode *else_node; Buf *err_symbol; + bool var_is_ptr; }; struct AstNodeTestExpr { @@ -993,12 +996,12 @@ struct AstNodeWhileExpr { Buf *name; AstNode *condition; Buf *var_symbol; - bool var_is_ptr; AstNode *continue_expr; AstNode *body; AstNode *else_node; Buf *err_symbol; bool is_inline; + bool var_is_ptr; }; struct AstNodeForExpr { @@ -1070,7 +1073,7 @@ struct AsmToken { }; struct AstNodeAsmExpr { - Token *volatile_token; + TokenIndex volatile_token; AstNode *asm_template; ZigList output_list; ZigList input_list; @@ -1094,7 +1097,7 @@ struct AstNodeContainerDecl { AstNode *init_arg_expr; // enum(T), struct(endianness), or union(T), or union(enum(T)) ZigList fields; ZigList decls; - Buf doc_comments; + TokenIndex doc_comments; ContainerKind kind; ContainerLayout layout; @@ -1103,7 +1106,7 @@ struct AstNodeContainerDecl { }; struct AstNodeErrorSetField { - Buf doc_comments; + TokenIndex doc_comments; AstNode *field_name; }; @@ -1118,28 +1121,8 @@ struct AstNodeStructField { AstNode *value; // populated if the "align(A)" is present AstNode *align_expr; - Buf doc_comments; - Token *comptime_token; -}; - -struct AstNodeStringLiteral { - Buf *buf; -}; - -struct AstNodeCharLiteral { - uint32_t value; -}; - -struct AstNodeFloatLiteral { - BigFloat *bigfloat; - - // overflow is true if when parsing the number, we discovered it would not - // fit without losing data in a double - bool overflow; -}; - -struct AstNodeIntLiteral { - BigInt *bigint; + TokenIndex doc_comments; + TokenIndex comptime_token; }; struct AstNodeStructValueField { @@ -1158,19 +1141,6 @@ struct AstNodeContainerInitExpr { ContainerInitKind kind; }; -struct AstNodeNullLiteral { -}; - -struct AstNodeUndefinedLiteral { -}; - -struct AstNodeThisLiteral { -}; - -struct AstNodeSymbolExpr { - Buf *symbol; -}; - struct AstNodeBoolLiteral { bool value; }; @@ -1188,13 +1158,6 @@ struct AstNodeContinueExpr { Buf *name; }; -struct AstNodeUnreachableExpr { -}; - - -struct AstNodeErrorType { -}; - struct AstNodeAwaitExpr { AstNode *expr; }; @@ -1207,16 +1170,10 @@ struct AstNodeAnyFrameType { AstNode *payload_type; // can be NULL }; -struct AstNodeEnumLiteral { - Token *period; - Token *identifier; -}; - struct AstNode { enum NodeType type; + TokenIndex main_token; bool already_traced_this_node; - size_t line; - size_t column; ZigType *owner; union { AstNodeFnDef fn_def; @@ -1252,30 +1209,19 @@ struct AstNode { AstNodePtrDerefExpr ptr_deref_expr; AstNodeContainerDecl container_decl; AstNodeStructField struct_field; - AstNodeStringLiteral string_literal; - AstNodeCharLiteral char_literal; - AstNodeFloatLiteral float_literal; - AstNodeIntLiteral int_literal; AstNodeContainerInitExpr container_init_expr; AstNodeStructValueField struct_val_field; - AstNodeNullLiteral null_literal; - AstNodeUndefinedLiteral undefined_literal; - AstNodeThisLiteral this_literal; - AstNodeSymbolExpr symbol_expr; AstNodeBoolLiteral bool_literal; AstNodeBreakExpr break_expr; AstNodeContinueExpr continue_expr; - AstNodeUnreachableExpr unreachable_expr; AstNodeArrayType array_type; AstNodeInferredArrayType inferred_array_type; - AstNodeErrorType error_type; AstNodeErrorSetDecl err_set_decl; AstNodeErrorSetField err_set_field; AstNodeResumeExpr resume_expr; AstNodeAwaitExpr await_expr; AstNodeSuspend suspend; AstNodeAnyFrameType anyframe_type; - AstNodeEnumLiteral enum_literal; } data; // This is a function for use in the debugger to print @@ -1409,9 +1355,11 @@ struct ZigPackage { struct RootStruct { ZigPackage *package; Buf *path; // relative to root_package->root_src_dir - ZigList *line_offsets; Buf *source_code; ZigLLVMDIFile *di_file; + size_t token_count; + TokenId *token_ids; + TokenLoc *token_locs; }; enum StructSpecial { diff --git a/src/stage1/analyze.cpp b/src/stage1/analyze.cpp index 581e34acfc..b675beb9e0 100644 --- a/src/stage1/analyze.cpp +++ b/src/stage1/analyze.cpp @@ -6,9 +6,9 @@ */ #include "analyze.hpp" -#include "ast_render.hpp" #include "codegen.hpp" #include "error.hpp" +#include "astgen.hpp" #include "ir.hpp" #include "ir_print.hpp" #include "os.hpp" @@ -41,41 +41,44 @@ static bool is_top_level_struct(ZigType *import) { return import->id == ZigTypeIdStruct && import->data.structure.root_struct != nullptr; } -static ErrorMsg *add_error_note_token(CodeGen *g, ErrorMsg *parent_msg, ZigType *owner, Token *token, Buf *msg) { +static ErrorMsg *add_error_note_token(CodeGen *g, ErrorMsg *parent_msg, ZigType *owner, + TokenIndex token, Buf *msg) +{ assert(is_top_level_struct(owner)); RootStruct *root_struct = owner->data.structure.root_struct; - - ErrorMsg *err = err_msg_create_with_line(root_struct->path, token->start_line, token->start_column, - root_struct->source_code, root_struct->line_offsets, msg); + uint32_t byte_offset = root_struct->token_locs[token].offset; + ErrorMsg *err = err_msg_create_with_offset(root_struct->path, byte_offset, + buf_ptr(root_struct->source_code), msg); err_msg_add_note(parent_msg, err); return err; } -ErrorMsg *add_token_error(CodeGen *g, ZigType *owner, Token *token, Buf *msg) { +ErrorMsg *add_token_error_offset(CodeGen *g, ZigType *owner, TokenIndex token, Buf *msg, + uint32_t bad_index) +{ assert(is_top_level_struct(owner)); RootStruct *root_struct = owner->data.structure.root_struct; - ErrorMsg *err = err_msg_create_with_line(root_struct->path, token->start_line, token->start_column, - root_struct->source_code, root_struct->line_offsets, msg); + uint32_t byte_offset = root_struct->token_locs[token].offset + bad_index; + ErrorMsg *err = err_msg_create_with_offset(root_struct->path, byte_offset, + buf_ptr(root_struct->source_code), msg); g->errors.append(err); g->trace_err = err; return err; } +ErrorMsg *add_token_error(CodeGen *g, ZigType *owner, TokenIndex token, Buf *msg) { + return add_token_error_offset(g, owner, token, msg, 0); +} + ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg) { - Token fake_token; - fake_token.start_line = node->line; - fake_token.start_column = node->column; node->already_traced_this_node = true; - return add_token_error(g, node->owner, &fake_token, msg); + return add_token_error(g, node->owner, node->main_token, msg); } ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, const AstNode *node, Buf *msg) { - Token fake_token; - fake_token.start_line = node->line; - fake_token.start_column = node->column; - return add_error_note_token(g, parent_msg, node->owner, &fake_token, msg); + return add_error_note_token(g, parent_msg, node->owner, node->main_token, msg); } ZigType *new_type_table_entry(ZigTypeId id) { @@ -913,13 +916,27 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) { return entry; } -ZigType *get_opaque_type(CodeGen *g, Scope *scope, AstNode *source_node, const char *full_name, Buf *bare_name) { +static uint32_t node_line_onebased(AstNode *node) { + RootStruct *root_struct = node->owner->data.structure.root_struct; + assert(node->main_token < root_struct->token_count); + return root_struct->token_locs[node->main_token].line + 1; +} + +static uint32_t node_column_onebased(AstNode *node) { + RootStruct *root_struct = node->owner->data.structure.root_struct; + assert(node->main_token < root_struct->token_count); + return root_struct->token_locs[node->main_token].column + 1; +} + +ZigType *get_opaque_type(CodeGen *g, Scope *scope, AstNode *source_node, const char *full_name, + Buf *bare_name) +{ ZigType *entry = new_type_table_entry(ZigTypeIdOpaque); buf_init_from_str(&entry->name, full_name); ZigType *import = scope ? get_scope_import(scope) : nullptr; - unsigned line = source_node ? (unsigned)(source_node->line + 1) : 0; + unsigned line = source_node ? node_line_onebased(source_node) : 0; // Note: duplicated in get_partial_container_type entry->llvm_type = LLVMInt8Type(); @@ -1142,7 +1159,7 @@ ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind break; case ContainerKindOpaque: { ZigType *import = scope ? get_scope_import(scope) : nullptr; - unsigned line = decl_node ? (unsigned)(decl_node->line + 1) : 0; + unsigned line = decl_node ? node_line_onebased(decl_node) : 0; // Note: duplicated in get_opaque_type entry->llvm_type = LLVMInt8Type(); entry->llvm_di_type = ZigLLVMCreateDebugForwardDeclType(g->dbuilder, @@ -1584,8 +1601,9 @@ static OnePossibleValue type_val_resolve_has_one_possible_value(CodeGen *g, ZigV ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) { Error err; // Hot path for simple identifiers, to avoid unnecessary memory allocations. - if (node->type == NodeTypeSymbol) { - Buf *variable_name = node->data.symbol_expr.symbol; + if (node->type == NodeTypeIdentifier) { + RootStruct *root_struct = node->owner->data.structure.root_struct; + Buf *variable_name = token_identifier_buf(root_struct, node->main_token); if (buf_eql_str(variable_name, "_")) goto abort_hot_path; ZigType *primitive_type; @@ -2034,7 +2052,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc buf_sprintf("var args only allowed in functions with C calling convention")); return g->builtin_types.entry_invalid; } - } else if (param_node->data.param_decl.anytype_token != nullptr) { + } else if (param_node->data.param_decl.anytype_token != 0) { if (!calling_convention_allows_zig_types(fn_type_id.cc)) { add_node_error(g, param_node, buf_sprintf("parameter of type 'anytype' not allowed in function with calling convention '%s'", @@ -3021,7 +3039,7 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { field_node = decl_node->data.container_decl.fields.at(i); type_struct_field->name = field_node->data.struct_field.name; type_struct_field->decl_node = field_node; - if (field_node->data.struct_field.comptime_token != nullptr) { + if (field_node->data.struct_field.comptime_token != 0) { if (field_node->data.struct_field.value == nullptr) { add_token_error(g, field_node->owner, field_node->data.struct_field.comptime_token, @@ -4042,7 +4060,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) { case NodeTypeBoolLiteral: case NodeTypeNullLiteral: case NodeTypeUndefinedLiteral: - case NodeTypeSymbol: + case NodeTypeIdentifier: case NodeTypePrefixOpExpr: case NodeTypePointerType: case NodeTypeIfBoolExpr: @@ -4238,7 +4256,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var, bool allow_lazy) { bool is_const = var_decl->is_const; bool is_extern = var_decl->is_extern; bool is_export = var_decl->is_export; - bool is_thread_local = var_decl->threadlocal_tok != nullptr; + bool is_thread_local = var_decl->threadlocal_tok != 0; ZigType *explicit_type = nullptr; if (var_decl->type) { @@ -5225,8 +5243,6 @@ static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry) { } if (g->verbose_ir) { - fprintf(stderr, "\n"); - ast_render(stderr, fn_table_entry->body_node, 4); fprintf(stderr, "\nfn %s() { // (IR)\n", buf_ptr(&fn_table_entry->symbol_name)); ir_print_src(g, stderr, fn_table_entry->ir_executable, 4); fprintf(stderr, "}\n"); @@ -5238,33 +5254,17 @@ static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry) { ZigType *add_source_file(CodeGen *g, ZigPackage *package, Buf *resolved_path, Buf *source_code, SourceKind source_kind) { - if (g->verbose_tokenize) { - fprintf(stderr, "\nOriginal Source (%s):\n", buf_ptr(resolved_path)); - fprintf(stderr, "----------------\n"); - fprintf(stderr, "%s\n", buf_ptr(source_code)); - - fprintf(stderr, "\nTokens:\n"); - fprintf(stderr, "---------\n"); - } - Tokenization tokenization = {0}; - tokenize(source_code, &tokenization); + tokenize(buf_ptr(source_code), &tokenization); if (tokenization.err) { - ErrorMsg *err = err_msg_create_with_line(resolved_path, tokenization.err_line, tokenization.err_column, - source_code, tokenization.line_offsets, tokenization.err); + ErrorMsg *err = err_msg_create_with_offset(resolved_path, tokenization.err_byte_offset, + buf_ptr(source_code), tokenization.err); print_err_msg(err, g->err_color); exit(1); } - if (g->verbose_tokenize) { - print_tokens(source_code, tokenization.tokens); - - fprintf(stderr, "\nAST:\n"); - fprintf(stderr, "------\n"); - } - Buf *src_dirname = buf_alloc(); Buf *src_basename = buf_alloc(); os_path_split(resolved_path, src_dirname, src_basename); @@ -5297,9 +5297,20 @@ ZigType *add_source_file(CodeGen *g, ZigPackage *package, Buf *resolved_path, Bu RootStruct *root_struct = heap::c_allocator.create(); root_struct->package = package; root_struct->source_code = source_code; - root_struct->line_offsets = tokenization.line_offsets; root_struct->path = resolved_path; root_struct->di_file = ZigLLVMCreateFile(g->dbuilder, buf_ptr(src_basename), buf_ptr(src_dirname)); + + assert(tokenization.ids.length == tokenization.locs.length); + size_t token_count = tokenization.ids.length; + root_struct->token_count = token_count; + root_struct->token_ids = g->pass1_arena->allocate(token_count); + memcpy(root_struct->token_ids, tokenization.ids.items, token_count * sizeof(TokenId)); + root_struct->token_locs = g->pass1_arena->allocate(token_count); + memcpy(root_struct->token_locs, tokenization.locs.items, token_count * sizeof(TokenLoc)); + + tokenization.ids.deinit(); + tokenization.locs.deinit(); + ZigType *import_entry = get_root_container_type(g, buf_ptr(namespace_name), bare_name, root_struct); if (source_kind == SourceKindRoot) { assert(g->root_import == nullptr); @@ -5307,14 +5318,11 @@ ZigType *add_source_file(CodeGen *g, ZigPackage *package, Buf *resolved_path, Bu } g->import_table.put(resolved_path, import_entry); - AstNode *root_node = ast_parse(source_code, tokenization.tokens, import_entry, g->err_color); + AstNode *root_node = ast_parse(source_code, import_entry, g->err_color); assert(root_node != nullptr); assert(root_node->type == NodeTypeContainerDecl); import_entry->data.structure.decl_node = root_node; import_entry->data.structure.decls_scope->base.source_node = root_node; - if (g->verbose_ast) { - ast_print(stderr, root_node, 0); - } for (size_t decl_i = 0; decl_i < root_node->data.container_decl.decls.length; decl_i += 1) { AstNode *top_level_decl = root_node->data.container_decl.decls.at(decl_i); @@ -6254,9 +6262,12 @@ ReqCompTime type_requires_comptime(CodeGen *g, ZigType *ty) { zig_unreachable(); } -void init_const_str_lit(CodeGen *g, ZigValue *const_val, Buf *str) { +void init_const_str_lit(CodeGen *g, ZigValue *const_val, Buf *str, bool move_str) { auto entry = g->string_literals_table.maybe_get(str); if (entry != nullptr) { + if (move_str) { + buf_destroy(str); + } memcpy(const_val, entry->value, sizeof(ZigValue)); return; } @@ -6280,7 +6291,7 @@ void init_const_str_lit(CodeGen *g, ZigValue *const_val, Buf *str) { ZigValue *create_const_str_lit(CodeGen *g, Buf *str) { ZigValue *const_val = g->pass1_arena->create(); - init_const_str_lit(g, const_val, str); + init_const_str_lit(g, const_val, str, false); return const_val; } @@ -8626,7 +8637,7 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS ZigType *import = get_scope_import(scope); di_file = import->data.structure.root_struct->di_file; di_scope = ZigLLVMFileToScope(di_file); - line = decl_node->line + 1; + line = node_line_onebased(decl_node); } else { di_file = nullptr; di_scope = ZigLLVMCompileUnitToScope(g->compile_unit); @@ -8830,7 +8841,7 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS unsigned line; if (decl_node != nullptr) { AstNode *field_node = field->decl_node; - line = field_node->line + 1; + line = node_line_onebased(field_node); } else { line = 0; } @@ -8881,7 +8892,7 @@ static ZigLLVMDIType *make_empty_namespace_llvm_di_type(CodeGen *g, ZigType *imp return ZigLLVMCreateDebugStructType(g->dbuilder, ZigLLVMFileToScope(import->data.structure.root_struct->di_file), name, - import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1), + import->data.structure.root_struct->di_file, node_line_onebased(decl_node), debug_size_in_bits, debug_align_in_bits, ZigLLVM_DIFlags_Zero, @@ -8926,7 +8937,7 @@ static void resolve_llvm_types_enum(CodeGen *g, ZigType *enum_type, ResolveStatu uint64_t tag_debug_align_in_bits = 8*tag_int_type->abi_align; ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder, ZigLLVMFileToScope(import->data.structure.root_struct->di_file), buf_ptr(&enum_type->name), - import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1), + import->data.structure.root_struct->di_file, node_line_onebased(decl_node), tag_debug_size_in_bits, tag_debug_align_in_bits, di_enumerators, field_count, @@ -8966,12 +8977,12 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta if (union_type->data.unionation.resolve_status < ResolveStatusLLVMFwdDecl) { union_type->llvm_type = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(&union_type->name)); - size_t line = decl_node ? decl_node->line : 0; + unsigned line = decl_node ? node_line_onebased(decl_node) : 0; unsigned dwarf_kind = ZigLLVMTag_DW_structure_type(); union_type->llvm_di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder, dwarf_kind, buf_ptr(&union_type->name), ZigLLVMFileToScope(import->data.structure.root_struct->di_file), - import->data.structure.root_struct->di_file, (unsigned)(line + 1)); + import->data.structure.root_struct->di_file, line); union_type->data.unionation.resolve_status = ResolveStatusLLVMFwdDecl; if (ResolveStatusLLVMFwdDecl >= wanted_resolve_status) return; @@ -8992,7 +9003,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta AstNode *field_node = union_field->decl_node; union_inner_di_types[union_field->gen_index] = ZigLLVMCreateDebugMemberType(g->dbuilder, ZigLLVMTypeToScope(union_type->llvm_di_type), buf_ptr(union_field->enum_field->name), - import->data.structure.root_struct->di_file, (unsigned)(field_node->line + 1), + import->data.structure.root_struct->di_file, node_line_onebased(field_node), store_size_in_bits, abi_align_in_bits, 0, @@ -9022,7 +9033,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta // create debug type for union ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugUnionType(g->dbuilder, ZigLLVMFileToScope(import->data.structure.root_struct->di_file), buf_ptr(&union_type->name), - import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1), + import->data.structure.root_struct->di_file, node_line_onebased(decl_node), union_type->data.unionation.union_abi_size * 8, most_aligned_union_member->align * 8, ZigLLVM_DIFlags_Zero, union_inner_di_types, @@ -9057,7 +9068,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta // create debug type for union ZigLLVMDIType *union_di_type = ZigLLVMCreateDebugUnionType(g->dbuilder, ZigLLVMTypeToScope(union_type->llvm_di_type), "AnonUnion", - import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1), + import->data.structure.root_struct->di_file, node_line_onebased(decl_node), most_aligned_union_member->type_entry->size_in_bits, 8*most_aligned_union_member->align, ZigLLVM_DIFlags_Zero, union_inner_di_types, gen_field_count, 0, ""); @@ -9068,7 +9079,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta ZigLLVMDIType *union_member_di_type = ZigLLVMCreateDebugMemberType(g->dbuilder, ZigLLVMTypeToScope(union_type->llvm_di_type), "payload", - import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1), + import->data.structure.root_struct->di_file, node_line_onebased(decl_node), most_aligned_union_member->type_entry->size_in_bits, 8*most_aligned_union_member->align, union_offset_in_bits, @@ -9079,7 +9090,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta ZigLLVMDIType *tag_member_di_type = ZigLLVMCreateDebugMemberType(g->dbuilder, ZigLLVMTypeToScope(union_type->llvm_di_type), "tag", - import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1), + import->data.structure.root_struct->di_file, node_line_onebased(decl_node), tag_debug_size_in_bits, tag_debug_align_in_bits, tag_offset_in_bits, @@ -9094,7 +9105,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder, ZigLLVMFileToScope(import->data.structure.root_struct->di_file), buf_ptr(&union_type->name), - import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1), + import->data.structure.root_struct->di_file, node_line_onebased(decl_node), debug_size_in_bits, debug_align_in_bits, ZigLLVM_DIFlags_Zero, nullptr, di_root_members, 2, 0, nullptr, ""); @@ -9774,9 +9785,9 @@ void src_assert_impl(bool ok, AstNode *source_node, char const *file, unsigned i if (source_node == nullptr) { fprintf(stderr, "when analyzing (unknown source location) "); } else { - fprintf(stderr, "when analyzing %s:%u:%u ", - buf_ptr(source_node->owner->data.structure.root_struct->path), - (unsigned)source_node->line + 1, (unsigned)source_node->column + 1); + RootStruct *root_struct = source_node->owner->data.structure.root_struct; + fprintf(stderr, "when analyzing %s:%u:%u ", buf_ptr(root_struct->path), + node_line_onebased(source_node), node_column_onebased(source_node)); } fprintf(stderr, "in compiler source at %s:%u: ", file, line); const char *msg = "assertion failed. This is a bug in the Zig compiler."; @@ -9842,6 +9853,14 @@ Error analyze_import(CodeGen *g, ZigType *source_import, Buf *import_target_str, return ErrorNone; } +void AstNode::src() { + RootStruct *root_struct = this->owner->data.structure.root_struct; + uint32_t line = root_struct->token_locs[this->main_token].line + 1; + uint32_t column = root_struct->token_locs[this->main_token].column + 1; + fprintf(stderr, "%s:%" PRIu32 ":%" PRIu32 "\n", + buf_ptr(root_struct->path), + line, column); +} void IrExecutableSrc::src() { if (this->source_node != nullptr) { diff --git a/src/stage1/analyze.hpp b/src/stage1/analyze.hpp index 2815274f63..fee83ab7d0 100644 --- a/src/stage1/analyze.hpp +++ b/src/stage1/analyze.hpp @@ -12,7 +12,9 @@ void semantic_analyze(CodeGen *g); ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg); -ErrorMsg *add_token_error(CodeGen *g, ZigType *owner, Token *token, Buf *msg); +ErrorMsg *add_token_error(CodeGen *g, ZigType *owner, TokenIndex token, Buf *msg); +ErrorMsg *add_token_error_offset(CodeGen *g, ZigType *owner, TokenIndex token, Buf *msg, + uint32_t bad_index); ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, const AstNode *node, Buf *msg); ZigType *new_type_table_entry(ZigTypeId id); ZigType *get_fn_frame_type(CodeGen *g, ZigFn *fn); @@ -140,7 +142,7 @@ Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, IrInstSrc Scope *create_typeof_scope(CodeGen *g, AstNode *node, Scope *parent); ScopeExpr *create_expr_scope(CodeGen *g, AstNode *node, Scope *parent); -void init_const_str_lit(CodeGen *g, ZigValue *const_val, Buf *str); +void init_const_str_lit(CodeGen *g, ZigValue *const_val, Buf *str, bool move_str); ZigValue *create_const_str_lit(CodeGen *g, Buf *str); void init_const_bigint(ZigValue *const_val, ZigType *type, const BigInt *bigint); diff --git a/src/stage1/ast_render.cpp b/src/stage1/ast_render.cpp deleted file mode 100644 index 75ad7267ab..0000000000 --- a/src/stage1/ast_render.cpp +++ /dev/null @@ -1,1241 +0,0 @@ -/* - * Copyright (c) 2016 Andrew Kelley - * - * This file is part of zig, which is MIT licensed. - * See http://opensource.org/licenses/MIT - */ - -#include "analyze.hpp" -#include "ast_render.hpp" -#include "os.hpp" - -#include - -static const char *bin_op_str(BinOpType bin_op) { - switch (bin_op) { - case BinOpTypeInvalid: return "(invalid)"; - case BinOpTypeBoolOr: return "or"; - case BinOpTypeBoolAnd: return "and"; - case BinOpTypeCmpEq: return "=="; - case BinOpTypeCmpNotEq: return "!="; - case BinOpTypeCmpLessThan: return "<"; - case BinOpTypeCmpGreaterThan: return ">"; - case BinOpTypeCmpLessOrEq: return "<="; - case BinOpTypeCmpGreaterOrEq: return ">="; - case BinOpTypeBinOr: return "|"; - case BinOpTypeBinXor: return "^"; - case BinOpTypeBinAnd: return "&"; - case BinOpTypeBitShiftLeft: return "<<"; - case BinOpTypeBitShiftRight: return ">>"; - case BinOpTypeAdd: return "+"; - case BinOpTypeAddWrap: return "+%"; - case BinOpTypeSub: return "-"; - case BinOpTypeSubWrap: return "-%"; - case BinOpTypeMult: return "*"; - case BinOpTypeMultWrap: return "*%"; - case BinOpTypeDiv: return "/"; - case BinOpTypeMod: return "%"; - case BinOpTypeAssign: return "="; - case BinOpTypeAssignTimes: return "*="; - case BinOpTypeAssignTimesWrap: return "*%="; - case BinOpTypeAssignDiv: return "/="; - case BinOpTypeAssignMod: return "%="; - case BinOpTypeAssignPlus: return "+="; - case BinOpTypeAssignPlusWrap: return "+%="; - case BinOpTypeAssignMinus: return "-="; - case BinOpTypeAssignMinusWrap: return "-%="; - case BinOpTypeAssignBitShiftLeft: return "<<="; - case BinOpTypeAssignBitShiftRight: return ">>="; - case BinOpTypeAssignBitAnd: return "&="; - case BinOpTypeAssignBitXor: return "^="; - case BinOpTypeAssignBitOr: return "|="; - case BinOpTypeUnwrapOptional: return "orelse"; - case BinOpTypeArrayCat: return "++"; - case BinOpTypeArrayMult: return "**"; - case BinOpTypeErrorUnion: return "!"; - case BinOpTypeMergeErrorSets: return "||"; - } - zig_unreachable(); -} - -static const char *prefix_op_str(PrefixOp prefix_op) { - switch (prefix_op) { - case PrefixOpInvalid: return "(invalid)"; - case PrefixOpNegation: return "-"; - case PrefixOpNegationWrap: return "-%"; - case PrefixOpBoolNot: return "!"; - case PrefixOpBinNot: return "~"; - case PrefixOpOptional: return "?"; - case PrefixOpAddrOf: return "&"; - } - zig_unreachable(); -} - -static const char *visib_mod_string(VisibMod mod) { - switch (mod) { - case VisibModPub: return "pub "; - case VisibModPrivate: return ""; - } - zig_unreachable(); -} - -static const char *return_string(ReturnKind kind) { - switch (kind) { - case ReturnKindUnconditional: return "return"; - case ReturnKindError: return "try"; - } - zig_unreachable(); -} - -static const char *defer_string(ReturnKind kind) { - switch (kind) { - case ReturnKindUnconditional: return "defer"; - case ReturnKindError: return "errdefer"; - } - zig_unreachable(); -} - -static const char *layout_string(ContainerLayout layout) { - switch (layout) { - case ContainerLayoutAuto: return ""; - case ContainerLayoutExtern: return "extern "; - case ContainerLayoutPacked: return "packed "; - } - zig_unreachable(); -} - -static const char *extern_string(bool is_extern) { - return is_extern ? "extern " : ""; -} - -static const char *export_string(bool is_export) { - return is_export ? "export " : ""; -} - -//static const char *calling_convention_string(CallingConvention cc) { -// switch (cc) { -// case CallingConventionUnspecified: return ""; -// case CallingConventionC: return "extern "; -// case CallingConventionCold: return "coldcc "; -// case CallingConventionNaked: return "nakedcc "; -// case CallingConventionStdcall: return "stdcallcc "; -// } -// zig_unreachable(); -//} - -static const char *inline_string(FnInline fn_inline) { - switch (fn_inline) { - case FnInlineAlways: return "inline "; - case FnInlineNever: return "noinline "; - case FnInlineAuto: return ""; - } - zig_unreachable(); -} - -static const char *const_or_var_string(bool is_const) { - return is_const ? "const" : "var"; -} - -static const char *thread_local_string(Token *tok) { - return (tok == nullptr) ? "" : "threadlocal "; -} - -static const char *token_to_ptr_len_str(Token *tok) { - assert(tok != nullptr); - switch (tok->id) { - case TokenIdStar: - case TokenIdStarStar: - return "*"; - case TokenIdLBracket: - return "[*]"; - case TokenIdSymbol: - return "[*c]"; - default: - zig_unreachable(); - } -} - -static const char *node_type_str(NodeType node_type) { - switch (node_type) { - case NodeTypeFnDef: - return "FnDef"; - case NodeTypeFnProto: - return "FnProto"; - case NodeTypeParamDecl: - return "ParamDecl"; - case NodeTypeBlock: - return "Block"; - case NodeTypeGroupedExpr: - return "Parens"; - case NodeTypeBinOpExpr: - return "BinOpExpr"; - case NodeTypeCatchExpr: - return "CatchExpr"; - case NodeTypeFnCallExpr: - return "FnCallExpr"; - case NodeTypeArrayAccessExpr: - return "ArrayAccessExpr"; - case NodeTypeSliceExpr: - return "SliceExpr"; - case NodeTypeReturnExpr: - return "ReturnExpr"; - case NodeTypeDefer: - return "Defer"; - case NodeTypeVariableDeclaration: - return "VariableDeclaration"; - case NodeTypeTestDecl: - return "TestDecl"; - case NodeTypeIntLiteral: - return "IntLiteral"; - case NodeTypeFloatLiteral: - return "FloatLiteral"; - case NodeTypeStringLiteral: - return "StringLiteral"; - case NodeTypeCharLiteral: - return "CharLiteral"; - case NodeTypeSymbol: - return "Symbol"; - case NodeTypePrefixOpExpr: - return "PrefixOpExpr"; - case NodeTypeUsingNamespace: - return "UsingNamespace"; - case NodeTypeBoolLiteral: - return "BoolLiteral"; - case NodeTypeNullLiteral: - return "NullLiteral"; - case NodeTypeUndefinedLiteral: - return "UndefinedLiteral"; - case NodeTypeIfBoolExpr: - return "IfBoolExpr"; - case NodeTypeWhileExpr: - return "WhileExpr"; - case NodeTypeForExpr: - return "ForExpr"; - case NodeTypeSwitchExpr: - return "SwitchExpr"; - case NodeTypeSwitchProng: - return "SwitchProng"; - case NodeTypeSwitchRange: - return "SwitchRange"; - case NodeTypeCompTime: - return "CompTime"; - case NodeTypeNoSuspend: - return "NoSuspend"; - case NodeTypeBreak: - return "Break"; - case NodeTypeContinue: - return "Continue"; - case NodeTypeUnreachable: - return "Unreachable"; - case NodeTypeAsmExpr: - return "AsmExpr"; - case NodeTypeFieldAccessExpr: - return "FieldAccessExpr"; - case NodeTypePtrDeref: - return "PtrDerefExpr"; - case NodeTypeUnwrapOptional: - return "UnwrapOptional"; - case NodeTypeContainerDecl: - return "ContainerDecl"; - case NodeTypeStructField: - return "StructField"; - case NodeTypeStructValueField: - return "StructValueField"; - case NodeTypeContainerInitExpr: - return "ContainerInitExpr"; - case NodeTypeArrayType: - return "ArrayType"; - case NodeTypeInferredArrayType: - return "InferredArrayType"; - case NodeTypeErrorType: - return "ErrorType"; - case NodeTypeIfErrorExpr: - return "IfErrorExpr"; - case NodeTypeIfOptional: - return "IfOptional"; - case NodeTypeErrorSetDecl: - return "ErrorSetDecl"; - case NodeTypeResume: - return "Resume"; - case NodeTypeAwaitExpr: - return "AwaitExpr"; - case NodeTypeSuspend: - return "Suspend"; - case NodeTypePointerType: - return "PointerType"; - case NodeTypeAnyFrameType: - return "AnyFrameType"; - case NodeTypeEnumLiteral: - return "EnumLiteral"; - case NodeTypeErrorSetField: - return "ErrorSetField"; - case NodeTypeAnyTypeField: - return "AnyTypeField"; - } - zig_unreachable(); -} - -struct AstPrint { - int indent; - FILE *f; -}; - -static void ast_print_visit(AstNode **node_ptr, void *context) { - AstNode *node = *node_ptr; - AstPrint *ap = (AstPrint *)context; - - for (int i = 0; i < ap->indent; i += 1) { - fprintf(ap->f, " "); - } - - fprintf(ap->f, "%s\n", node_type_str(node->type)); - - AstPrint new_ap; - new_ap.indent = ap->indent + 2; - new_ap.f = ap->f; - - ast_visit_node_children(node, ast_print_visit, &new_ap); -} - -void ast_print(FILE *f, AstNode *node, int indent) { - AstPrint ap; - ap.indent = indent; - ap.f = f; - ast_visit_node_children(node, ast_print_visit, &ap); -} - - -struct AstRender { - int indent; - int indent_size; - FILE *f; -}; - -static void print_indent(AstRender *ar) { - for (int i = 0; i < ar->indent; i += 1) { - fprintf(ar->f, " "); - } -} - -static bool is_alpha_under(uint8_t c) { - return (c >= 'a' && c <= 'z') || - (c >= 'A' && c <= 'Z') || c == '_'; -} - -static bool is_digit(uint8_t c) { - return (c >= '0' && c <= '9'); -} - -static bool is_printable(uint8_t c) { - if (c == 0) { - return false; - } - static const uint8_t printables[] = - " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.~`!@#$%^&*()_-+=\\{}[];'\"?/<>,:"; - for (size_t i = 0; i < array_length(printables); i += 1) { - if (c == printables[i]) return true; - } - return false; -} - -static void string_literal_escape(Buf *source, Buf *dest) { - buf_resize(dest, 0); - for (size_t i = 0; i < buf_len(source); i += 1) { - uint8_t c = *((uint8_t*)buf_ptr(source) + i); - if (c == '\'') { - buf_append_str(dest, "\\'"); - } else if (c == '"') { - buf_append_str(dest, "\\\""); - } else if (c == '\\') { - buf_append_str(dest, "\\\\"); - } else if (c == '\n') { - buf_append_str(dest, "\\n"); - } else if (c == '\r') { - buf_append_str(dest, "\\r"); - } else if (c == '\t') { - buf_append_str(dest, "\\t"); - } else if (is_printable(c)) { - buf_append_char(dest, c); - } else { - buf_appendf(dest, "\\x%02x", (int)c); - } - } -} - -static bool is_valid_bare_symbol(Buf *symbol) { - if (buf_len(symbol) == 0) { - return false; - } - uint8_t first_char = *buf_ptr(symbol); - if (!is_alpha_under(first_char)) { - return false; - } - for (size_t i = 1; i < buf_len(symbol); i += 1) { - uint8_t c = *((uint8_t*)buf_ptr(symbol) + i); - if (!is_alpha_under(c) && !is_digit(c)) { - return false; - } - } - return true; -} - -static void print_symbol(AstRender *ar, Buf *symbol) { - if (is_zig_keyword(symbol)) { - fprintf(ar->f, "@\"%s\"", buf_ptr(symbol)); - return; - } - if (is_valid_bare_symbol(symbol)) { - fprintf(ar->f, "%s", buf_ptr(symbol)); - return; - } - Buf escaped = BUF_INIT; - string_literal_escape(symbol, &escaped); - fprintf(ar->f, "@\"%s\"", buf_ptr(&escaped)); -} - -static bool statement_terminates_without_semicolon(AstNode *node) { - switch (node->type) { - case NodeTypeIfBoolExpr: - if (node->data.if_bool_expr.else_node) - return statement_terminates_without_semicolon(node->data.if_bool_expr.else_node); - return node->data.if_bool_expr.then_block->type == NodeTypeBlock; - case NodeTypeIfErrorExpr: - if (node->data.if_err_expr.else_node) - return statement_terminates_without_semicolon(node->data.if_err_expr.else_node); - return node->data.if_err_expr.then_node->type == NodeTypeBlock; - case NodeTypeIfOptional: - if (node->data.test_expr.else_node) - return statement_terminates_without_semicolon(node->data.test_expr.else_node); - return node->data.test_expr.then_node->type == NodeTypeBlock; - case NodeTypeWhileExpr: - return node->data.while_expr.body->type == NodeTypeBlock; - case NodeTypeForExpr: - return node->data.for_expr.body->type == NodeTypeBlock; - case NodeTypeCompTime: - return node->data.comptime_expr.expr->type == NodeTypeBlock; - case NodeTypeDefer: - return node->data.defer.expr->type == NodeTypeBlock; - case NodeTypeSuspend: - return node->data.suspend.block != nullptr && node->data.suspend.block->type == NodeTypeBlock; - case NodeTypeSwitchExpr: - case NodeTypeBlock: - return true; - default: - return false; - } -} - -static void render_node_extra(AstRender *ar, AstNode *node, bool grouped); - -static void render_node_grouped(AstRender *ar, AstNode *node) { - return render_node_extra(ar, node, true); -} - -static void render_node_ungrouped(AstRender *ar, AstNode *node) { - return render_node_extra(ar, node, false); -} - -static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { - switch (node->type) { - case NodeTypeSwitchProng: - case NodeTypeSwitchRange: - case NodeTypeStructValueField: - zig_unreachable(); - case NodeTypeFnProto: - { - const char *pub_str = visib_mod_string(node->data.fn_proto.visib_mod); - const char *extern_str = extern_string(node->data.fn_proto.is_extern); - const char *export_str = export_string(node->data.fn_proto.is_export); - const char *inline_str = inline_string(node->data.fn_proto.fn_inline); - fprintf(ar->f, "%s%s%s%sfn ", pub_str, inline_str, export_str, extern_str); - if (node->data.fn_proto.name != nullptr) { - print_symbol(ar, node->data.fn_proto.name); - } - fprintf(ar->f, "("); - size_t arg_count = node->data.fn_proto.params.length; - for (size_t arg_i = 0; arg_i < arg_count; arg_i += 1) { - AstNode *param_decl = node->data.fn_proto.params.at(arg_i); - assert(param_decl->type == NodeTypeParamDecl); - if (param_decl->data.param_decl.name != nullptr) { - const char *noalias_str = param_decl->data.param_decl.is_noalias ? "noalias " : ""; - const char *inline_str = param_decl->data.param_decl.is_comptime ? "comptime " : ""; - fprintf(ar->f, "%s%s", noalias_str, inline_str); - print_symbol(ar, param_decl->data.param_decl.name); - fprintf(ar->f, ": "); - } - if (param_decl->data.param_decl.is_var_args) { - fprintf(ar->f, "..."); - } else if (param_decl->data.param_decl.anytype_token != nullptr) { - fprintf(ar->f, "anytype"); - } else { - render_node_grouped(ar, param_decl->data.param_decl.type); - } - - if (arg_i + 1 < arg_count) { - fprintf(ar->f, ", "); - } - } - if (node->data.fn_proto.is_var_args) { - fprintf(ar->f, ", ..."); - } - fprintf(ar->f, ")"); - if (node->data.fn_proto.align_expr) { - fprintf(ar->f, " align("); - render_node_grouped(ar, node->data.fn_proto.align_expr); - fprintf(ar->f, ")"); - } - if (node->data.fn_proto.section_expr) { - fprintf(ar->f, " section("); - render_node_grouped(ar, node->data.fn_proto.section_expr); - fprintf(ar->f, ")"); - } - if (node->data.fn_proto.callconv_expr) { - fprintf(ar->f, " callconv("); - render_node_grouped(ar, node->data.fn_proto.callconv_expr); - fprintf(ar->f, ")"); - } - - AstNode *return_type_node = node->data.fn_proto.return_type; - assert(return_type_node != nullptr); - fprintf(ar->f, " "); - if (node->data.fn_proto.auto_err_set) { - fprintf(ar->f, "!"); - } - render_node_grouped(ar, return_type_node); - break; - } - case NodeTypeFnDef: - { - render_node_grouped(ar, node->data.fn_def.fn_proto); - fprintf(ar->f, " "); - render_node_grouped(ar, node->data.fn_def.body); - break; - } - case NodeTypeBlock: - if (node->data.block.name != nullptr) { - fprintf(ar->f, "%s: ", buf_ptr(node->data.block.name)); - } - if (node->data.block.statements.length == 0) { - fprintf(ar->f, "{}"); - break; - } - fprintf(ar->f, "{\n"); - ar->indent += ar->indent_size; - for (size_t i = 0; i < node->data.block.statements.length; i += 1) { - AstNode *statement = node->data.block.statements.at(i); - print_indent(ar); - render_node_grouped(ar, statement); - - if (!statement_terminates_without_semicolon(statement)) - fprintf(ar->f, ";"); - - fprintf(ar->f, "\n"); - } - ar->indent -= ar->indent_size; - print_indent(ar); - fprintf(ar->f, "}"); - break; - case NodeTypeGroupedExpr: - fprintf(ar->f, "("); - render_node_ungrouped(ar, node->data.grouped_expr); - fprintf(ar->f, ")"); - break; - case NodeTypeReturnExpr: - { - const char *return_str = return_string(node->data.return_expr.kind); - fprintf(ar->f, "%s", return_str); - if (node->data.return_expr.expr) { - fprintf(ar->f, " "); - render_node_grouped(ar, node->data.return_expr.expr); - } - break; - } - case NodeTypeBreak: - { - fprintf(ar->f, "break"); - if (node->data.break_expr.name != nullptr) { - fprintf(ar->f, " :%s", buf_ptr(node->data.break_expr.name)); - } - if (node->data.break_expr.expr) { - fprintf(ar->f, " "); - render_node_grouped(ar, node->data.break_expr.expr); - } - break; - } - case NodeTypeDefer: - { - const char *defer_str = defer_string(node->data.defer.kind); - fprintf(ar->f, "%s ", defer_str); - render_node_grouped(ar, node->data.defer.expr); - break; - } - case NodeTypeVariableDeclaration: - { - const char *pub_str = visib_mod_string(node->data.variable_declaration.visib_mod); - const char *extern_str = extern_string(node->data.variable_declaration.is_extern); - const char *thread_local_str = thread_local_string(node->data.variable_declaration.threadlocal_tok); - const char *const_or_var = const_or_var_string(node->data.variable_declaration.is_const); - fprintf(ar->f, "%s%s%s%s ", pub_str, extern_str, thread_local_str, const_or_var); - print_symbol(ar, node->data.variable_declaration.symbol); - - if (node->data.variable_declaration.type) { - fprintf(ar->f, ": "); - render_node_grouped(ar, node->data.variable_declaration.type); - } - if (node->data.variable_declaration.align_expr) { - fprintf(ar->f, "align("); - render_node_grouped(ar, node->data.variable_declaration.align_expr); - fprintf(ar->f, ") "); - } - if (node->data.variable_declaration.section_expr) { - fprintf(ar->f, "section("); - render_node_grouped(ar, node->data.variable_declaration.section_expr); - fprintf(ar->f, ") "); - } - if (node->data.variable_declaration.expr) { - fprintf(ar->f, " = "); - render_node_grouped(ar, node->data.variable_declaration.expr); - } - break; - } - case NodeTypeBinOpExpr: - if (!grouped) fprintf(ar->f, "("); - render_node_ungrouped(ar, node->data.bin_op_expr.op1); - fprintf(ar->f, " %s ", bin_op_str(node->data.bin_op_expr.bin_op)); - render_node_ungrouped(ar, node->data.bin_op_expr.op2); - if (!grouped) fprintf(ar->f, ")"); - break; - case NodeTypeFloatLiteral: - { - Buf rendered_buf = BUF_INIT; - buf_resize(&rendered_buf, 0); - bigfloat_append_buf(&rendered_buf, node->data.float_literal.bigfloat); - fprintf(ar->f, "%s", buf_ptr(&rendered_buf)); - } - break; - case NodeTypeIntLiteral: - { - Buf rendered_buf = BUF_INIT; - buf_resize(&rendered_buf, 0); - bigint_append_buf(&rendered_buf, node->data.int_literal.bigint, 10); - fprintf(ar->f, "%s", buf_ptr(&rendered_buf)); - } - break; - case NodeTypeStringLiteral: - { - Buf tmp_buf = BUF_INIT; - string_literal_escape(node->data.string_literal.buf, &tmp_buf); - fprintf(ar->f, "\"%s\"", buf_ptr(&tmp_buf)); - } - break; - case NodeTypeCharLiteral: - { - uint8_t c = node->data.char_literal.value; - if (c == '\'') { - fprintf(ar->f, "'\\''"); - } else if (c == '\"') { - fprintf(ar->f, "'\\\"'"); - } else if (c == '\\') { - fprintf(ar->f, "'\\\\'"); - } else if (c == '\n') { - fprintf(ar->f, "'\\n'"); - } else if (c == '\r') { - fprintf(ar->f, "'\\r'"); - } else if (c == '\t') { - fprintf(ar->f, "'\\t'"); - } else if (is_printable(c)) { - fprintf(ar->f, "'%c'", c); - } else { - fprintf(ar->f, "'\\x%02x'", (int)c); - } - break; - } - case NodeTypeSymbol: - print_symbol(ar, node->data.symbol_expr.symbol); - break; - case NodeTypePrefixOpExpr: - { - if (!grouped) fprintf(ar->f, "("); - PrefixOp op = node->data.prefix_op_expr.prefix_op; - fprintf(ar->f, "%s", prefix_op_str(op)); - - AstNode *child_node = node->data.prefix_op_expr.primary_expr; - bool new_grouped = child_node->type == NodeTypePrefixOpExpr || child_node->type == NodeTypePointerType; - render_node_extra(ar, child_node, new_grouped); - if (!grouped) fprintf(ar->f, ")"); - break; - } - case NodeTypePointerType: - { - if (!grouped) fprintf(ar->f, "("); - const char *ptr_len_str = token_to_ptr_len_str(node->data.pointer_type.star_token); - fprintf(ar->f, "%s", ptr_len_str); - if (node->data.pointer_type.align_expr != nullptr) { - fprintf(ar->f, "align("); - render_node_grouped(ar, node->data.pointer_type.align_expr); - if (node->data.pointer_type.bit_offset_start != nullptr) { - assert(node->data.pointer_type.host_int_bytes != nullptr); - - Buf offset_start_buf = BUF_INIT; - buf_resize(&offset_start_buf, 0); - bigint_append_buf(&offset_start_buf, node->data.pointer_type.bit_offset_start, 10); - - Buf offset_end_buf = BUF_INIT; - buf_resize(&offset_end_buf, 0); - bigint_append_buf(&offset_end_buf, node->data.pointer_type.host_int_bytes, 10); - - fprintf(ar->f, ":%s:%s ", buf_ptr(&offset_start_buf), buf_ptr(&offset_end_buf)); - } - fprintf(ar->f, ") "); - } - if (node->data.pointer_type.is_const) { - fprintf(ar->f, "const "); - } - if (node->data.pointer_type.is_volatile) { - fprintf(ar->f, "volatile "); - } - - render_node_ungrouped(ar, node->data.pointer_type.op_expr); - if (!grouped) fprintf(ar->f, ")"); - break; - } - case NodeTypeFnCallExpr: - { - switch (node->data.fn_call_expr.modifier) { - case CallModifierNone: - break; - case CallModifierNoSuspend: - fprintf(ar->f, "nosuspend "); - break; - case CallModifierAsync: - fprintf(ar->f, "async "); - break; - case CallModifierNeverTail: - fprintf(ar->f, "notail "); - break; - case CallModifierNeverInline: - fprintf(ar->f, "noinline "); - break; - case CallModifierAlwaysTail: - fprintf(ar->f, "tail "); - break; - case CallModifierAlwaysInline: - fprintf(ar->f, "inline "); - break; - case CallModifierCompileTime: - fprintf(ar->f, "comptime "); - break; - case CallModifierBuiltin: - fprintf(ar->f, "@"); - break; - } - AstNode *fn_ref_node = node->data.fn_call_expr.fn_ref_expr; - bool grouped = (fn_ref_node->type != NodeTypePrefixOpExpr && fn_ref_node->type != NodeTypePointerType); - render_node_extra(ar, fn_ref_node, grouped); - fprintf(ar->f, "("); - for (size_t i = 0; i < node->data.fn_call_expr.params.length; i += 1) { - AstNode *param = node->data.fn_call_expr.params.at(i); - if (i != 0) { - fprintf(ar->f, ", "); - } - render_node_grouped(ar, param); - } - fprintf(ar->f, ")"); - break; - } - case NodeTypeArrayAccessExpr: - render_node_ungrouped(ar, node->data.array_access_expr.array_ref_expr); - fprintf(ar->f, "["); - render_node_grouped(ar, node->data.array_access_expr.subscript); - fprintf(ar->f, "]"); - break; - case NodeTypeFieldAccessExpr: - { - AstNode *lhs = node->data.field_access_expr.struct_expr; - Buf *rhs = node->data.field_access_expr.field_name; - if (lhs->type == NodeTypeErrorType) { - fprintf(ar->f, "error"); - } else { - render_node_ungrouped(ar, lhs); - } - fprintf(ar->f, "."); - print_symbol(ar, rhs); - break; - } - case NodeTypePtrDeref: - { - AstNode *lhs = node->data.ptr_deref_expr.target; - render_node_ungrouped(ar, lhs); - fprintf(ar->f, ".*"); - break; - } - case NodeTypeUnwrapOptional: - { - AstNode *lhs = node->data.unwrap_optional.expr; - render_node_ungrouped(ar, lhs); - fprintf(ar->f, ".?"); - break; - } - case NodeTypeUndefinedLiteral: - fprintf(ar->f, "undefined"); - break; - case NodeTypeContainerDecl: - { - if (!node->data.container_decl.is_root) { - const char *layout_str = layout_string(node->data.container_decl.layout); - const char *container_str = container_string(node->data.container_decl.kind); - fprintf(ar->f, "%s%s", layout_str, container_str); - if (node->data.container_decl.auto_enum) { - fprintf(ar->f, "(enum"); - } - if (node->data.container_decl.init_arg_expr != nullptr) { - fprintf(ar->f, "("); - render_node_grouped(ar, node->data.container_decl.init_arg_expr); - fprintf(ar->f, ")"); - } - if (node->data.container_decl.auto_enum) { - fprintf(ar->f, ")"); - } - - fprintf(ar->f, " {\n"); - ar->indent += ar->indent_size; - } - for (size_t field_i = 0; field_i < node->data.container_decl.fields.length; field_i += 1) { - AstNode *field_node = node->data.container_decl.fields.at(field_i); - assert(field_node->type == NodeTypeStructField); - print_indent(ar); - print_symbol(ar, field_node->data.struct_field.name); - if (field_node->data.struct_field.type != nullptr) { - fprintf(ar->f, ": "); - render_node_grouped(ar, field_node->data.struct_field.type); - } - if (field_node->data.struct_field.value != nullptr) { - fprintf(ar->f, " = "); - render_node_grouped(ar, field_node->data.struct_field.value); - } - fprintf(ar->f, ",\n"); - } - - for (size_t decl_i = 0; decl_i < node->data.container_decl.decls.length; decl_i += 1) { - AstNode *decls_node = node->data.container_decl.decls.at(decl_i); - render_node_grouped(ar, decls_node); - - if (decls_node->type == NodeTypeUsingNamespace || - decls_node->type == NodeTypeVariableDeclaration || - decls_node->type == NodeTypeFnProto) - { - fprintf(ar->f, ";"); - } - fprintf(ar->f, "\n"); - } - - if (!node->data.container_decl.is_root) { - ar->indent -= ar->indent_size; - print_indent(ar); - fprintf(ar->f, "}"); - } - break; - } - case NodeTypeContainerInitExpr: - if (node->data.container_init_expr.type != nullptr) { - render_node_ungrouped(ar, node->data.container_init_expr.type); - } - if (node->data.container_init_expr.kind == ContainerInitKindStruct) { - fprintf(ar->f, "{\n"); - ar->indent += ar->indent_size; - } else { - fprintf(ar->f, "{"); - } - for (size_t i = 0; i < node->data.container_init_expr.entries.length; i += 1) { - AstNode *entry = node->data.container_init_expr.entries.at(i); - if (entry->type == NodeTypeStructValueField) { - Buf *name = entry->data.struct_val_field.name; - AstNode *expr = entry->data.struct_val_field.expr; - print_indent(ar); - fprintf(ar->f, ".%s = ", buf_ptr(name)); - render_node_grouped(ar, expr); - fprintf(ar->f, ",\n"); - } else { - if (i != 0) - fprintf(ar->f, ", "); - render_node_grouped(ar, entry); - } - } - if (node->data.container_init_expr.kind == ContainerInitKindStruct) { - ar->indent -= ar->indent_size; - } - print_indent(ar); - fprintf(ar->f, "}"); - break; - case NodeTypeArrayType: - { - fprintf(ar->f, "["); - if (node->data.array_type.size) { - render_node_grouped(ar, node->data.array_type.size); - } - fprintf(ar->f, "]"); - if (node->data.array_type.is_const) { - fprintf(ar->f, "const "); - } - render_node_ungrouped(ar, node->data.array_type.child_type); - break; - } - case NodeTypeInferredArrayType: - { - fprintf(ar->f, "[_]"); - render_node_ungrouped(ar, node->data.inferred_array_type.child_type); - break; - } - case NodeTypeAnyFrameType: { - fprintf(ar->f, "anyframe"); - if (node->data.anyframe_type.payload_type != nullptr) { - fprintf(ar->f, "->"); - render_node_grouped(ar, node->data.anyframe_type.payload_type); - } - break; - } - case NodeTypeErrorType: - fprintf(ar->f, "anyerror"); - break; - case NodeTypeAsmExpr: - { - AstNodeAsmExpr *asm_expr = &node->data.asm_expr; - const char *volatile_str = (asm_expr->volatile_token != nullptr) ? " volatile" : ""; - fprintf(ar->f, "asm%s (", volatile_str); - render_node_ungrouped(ar, asm_expr->asm_template); - fprintf(ar->f, ")"); - print_indent(ar); - fprintf(ar->f, ": "); - for (size_t i = 0; i < asm_expr->output_list.length; i += 1) { - AsmOutput *asm_output = asm_expr->output_list.at(i); - - if (i != 0) { - fprintf(ar->f, ",\n"); - print_indent(ar); - } - - fprintf(ar->f, "[%s] \"%s\" (", - buf_ptr(asm_output->asm_symbolic_name), - buf_ptr(asm_output->constraint)); - if (asm_output->return_type) { - fprintf(ar->f, "-> "); - render_node_grouped(ar, asm_output->return_type); - } else { - fprintf(ar->f, "%s", buf_ptr(asm_output->variable_name)); - } - fprintf(ar->f, ")"); - } - fprintf(ar->f, "\n"); - print_indent(ar); - fprintf(ar->f, ": "); - for (size_t i = 0; i < asm_expr->input_list.length; i += 1) { - AsmInput *asm_input = asm_expr->input_list.at(i); - - if (i != 0) { - fprintf(ar->f, ",\n"); - print_indent(ar); - } - - fprintf(ar->f, "[%s] \"%s\" (", - buf_ptr(asm_input->asm_symbolic_name), - buf_ptr(asm_input->constraint)); - render_node_grouped(ar, asm_input->expr); - fprintf(ar->f, ")"); - } - fprintf(ar->f, "\n"); - print_indent(ar); - fprintf(ar->f, ": "); - for (size_t i = 0; i < asm_expr->clobber_list.length; i += 1) { - Buf *reg_name = asm_expr->clobber_list.at(i); - if (i != 0) fprintf(ar->f, ", "); - fprintf(ar->f, "\"%s\"", buf_ptr(reg_name)); - } - fprintf(ar->f, ")"); - break; - } - case NodeTypeWhileExpr: - { - if (node->data.while_expr.name != nullptr) { - fprintf(ar->f, "%s: ", buf_ptr(node->data.while_expr.name)); - } - const char *inline_str = node->data.while_expr.is_inline ? "inline " : ""; - fprintf(ar->f, "%swhile (", inline_str); - render_node_grouped(ar, node->data.while_expr.condition); - fprintf(ar->f, ") "); - if (node->data.while_expr.var_symbol) { - fprintf(ar->f, "|%s| ", buf_ptr(node->data.while_expr.var_symbol)); - } - if (node->data.while_expr.continue_expr) { - fprintf(ar->f, ": ("); - render_node_grouped(ar, node->data.while_expr.continue_expr); - fprintf(ar->f, ") "); - } - render_node_grouped(ar, node->data.while_expr.body); - if (node->data.while_expr.else_node) { - fprintf(ar->f, " else "); - if (node->data.while_expr.err_symbol) { - fprintf(ar->f, "|%s| ", buf_ptr(node->data.while_expr.err_symbol)); - } - render_node_grouped(ar, node->data.while_expr.else_node); - } - break; - } - case NodeTypeBoolLiteral: - { - const char *bool_str = node->data.bool_literal.value ? "true" : "false"; - fprintf(ar->f, "%s", bool_str); - break; - } - case NodeTypeIfBoolExpr: - { - fprintf(ar->f, "if ("); - render_node_grouped(ar, node->data.if_bool_expr.condition); - fprintf(ar->f, ") "); - render_node_grouped(ar, node->data.if_bool_expr.then_block); - if (node->data.if_bool_expr.else_node) { - fprintf(ar->f, " else "); - render_node_grouped(ar, node->data.if_bool_expr.else_node); - } - break; - } - case NodeTypeNullLiteral: - { - fprintf(ar->f, "null"); - break; - } - case NodeTypeIfErrorExpr: - { - fprintf(ar->f, "if ("); - render_node_grouped(ar, node->data.if_err_expr.target_node); - fprintf(ar->f, ") "); - if (node->data.if_err_expr.var_symbol) { - const char *ptr_str = node->data.if_err_expr.var_is_ptr ? "*" : ""; - const char *var_name = buf_ptr(node->data.if_err_expr.var_symbol); - fprintf(ar->f, "|%s%s| ", ptr_str, var_name); - } - render_node_grouped(ar, node->data.if_err_expr.then_node); - if (node->data.if_err_expr.else_node) { - fprintf(ar->f, " else "); - if (node->data.if_err_expr.err_symbol) { - fprintf(ar->f, "|%s| ", buf_ptr(node->data.if_err_expr.err_symbol)); - } - render_node_grouped(ar, node->data.if_err_expr.else_node); - } - break; - } - case NodeTypeIfOptional: - { - fprintf(ar->f, "if ("); - render_node_grouped(ar, node->data.test_expr.target_node); - fprintf(ar->f, ") "); - if (node->data.test_expr.var_symbol) { - const char *ptr_str = node->data.test_expr.var_is_ptr ? "*" : ""; - const char *var_name = buf_ptr(node->data.test_expr.var_symbol); - fprintf(ar->f, "|%s%s| ", ptr_str, var_name); - } - render_node_grouped(ar, node->data.test_expr.then_node); - if (node->data.test_expr.else_node) { - fprintf(ar->f, " else "); - render_node_grouped(ar, node->data.test_expr.else_node); - } - break; - } - case NodeTypeSwitchExpr: - { - AstNodeSwitchExpr *switch_expr = &node->data.switch_expr; - fprintf(ar->f, "switch ("); - render_node_grouped(ar, switch_expr->expr); - fprintf(ar->f, ") {\n"); - ar->indent += ar->indent_size; - - for (size_t prong_i = 0; prong_i < switch_expr->prongs.length; prong_i += 1) { - AstNode *prong_node = switch_expr->prongs.at(prong_i); - AstNodeSwitchProng *switch_prong = &prong_node->data.switch_prong; - print_indent(ar); - for (size_t item_i = 0; item_i < switch_prong->items.length; item_i += 1) { - AstNode *item_node = switch_prong->items.at(item_i); - if (item_i != 0) - fprintf(ar->f, ", "); - if (item_node->type == NodeTypeSwitchRange) { - AstNode *start_node = item_node->data.switch_range.start; - AstNode *end_node = item_node->data.switch_range.end; - render_node_grouped(ar, start_node); - fprintf(ar->f, "..."); - render_node_grouped(ar, end_node); - } else { - render_node_grouped(ar, item_node); - } - } - const char *else_str = (switch_prong->items.length == 0) ? "else" : ""; - fprintf(ar->f, "%s => ", else_str); - if (switch_prong->var_symbol) { - const char *star_str = switch_prong->var_is_ptr ? "*" : ""; - Buf *var_name = switch_prong->var_symbol->data.symbol_expr.symbol; - fprintf(ar->f, "|%s%s| ", star_str, buf_ptr(var_name)); - } - render_node_grouped(ar, switch_prong->expr); - fprintf(ar->f, ",\n"); - } - - ar->indent -= ar->indent_size; - print_indent(ar); - fprintf(ar->f, "}"); - break; - } - case NodeTypeCompTime: - { - fprintf(ar->f, "comptime "); - render_node_grouped(ar, node->data.comptime_expr.expr); - break; - } - case NodeTypeNoSuspend: - { - fprintf(ar->f, "nosuspend "); - render_node_grouped(ar, node->data.nosuspend_expr.expr); - break; - } - case NodeTypeForExpr: - { - if (node->data.for_expr.name != nullptr) { - fprintf(ar->f, "%s: ", buf_ptr(node->data.for_expr.name)); - } - const char *inline_str = node->data.for_expr.is_inline ? "inline " : ""; - fprintf(ar->f, "%sfor (", inline_str); - render_node_grouped(ar, node->data.for_expr.array_expr); - fprintf(ar->f, ") "); - if (node->data.for_expr.elem_node) { - fprintf(ar->f, "|"); - if (node->data.for_expr.elem_is_ptr) - fprintf(ar->f, "*"); - render_node_grouped(ar, node->data.for_expr.elem_node); - if (node->data.for_expr.index_node) { - fprintf(ar->f, ", "); - render_node_grouped(ar, node->data.for_expr.index_node); - } - fprintf(ar->f, "| "); - } - render_node_grouped(ar, node->data.for_expr.body); - if (node->data.for_expr.else_node) { - fprintf(ar->f, " else"); - render_node_grouped(ar, node->data.for_expr.else_node); - } - break; - } - case NodeTypeContinue: - { - fprintf(ar->f, "continue"); - if (node->data.continue_expr.name != nullptr) { - fprintf(ar->f, " :%s", buf_ptr(node->data.continue_expr.name)); - } - break; - } - case NodeTypeUnreachable: - { - fprintf(ar->f, "unreachable"); - break; - } - case NodeTypeSliceExpr: - { - render_node_ungrouped(ar, node->data.slice_expr.array_ref_expr); - fprintf(ar->f, "["); - render_node_grouped(ar, node->data.slice_expr.start); - fprintf(ar->f, ".."); - if (node->data.slice_expr.end) - render_node_grouped(ar, node->data.slice_expr.end); - fprintf(ar->f, "]"); - break; - } - case NodeTypeCatchExpr: - { - render_node_ungrouped(ar, node->data.unwrap_err_expr.op1); - fprintf(ar->f, " catch "); - if (node->data.unwrap_err_expr.symbol) { - Buf *var_name = node->data.unwrap_err_expr.symbol->data.symbol_expr.symbol; - fprintf(ar->f, "|%s| ", buf_ptr(var_name)); - } - render_node_ungrouped(ar, node->data.unwrap_err_expr.op2); - break; - } - case NodeTypeErrorSetDecl: - { - fprintf(ar->f, "error {\n"); - ar->indent += ar->indent_size; - - for (size_t i = 0; i < node->data.err_set_decl.decls.length; i += 1) { - AstNode *field_node = node->data.err_set_decl.decls.at(i); - switch (field_node->type) { - case NodeTypeSymbol: - print_indent(ar); - print_symbol(ar, field_node->data.symbol_expr.symbol); - fprintf(ar->f, ",\n"); - break; - case NodeTypeErrorSetField: - print_indent(ar); - print_symbol(ar, field_node->data.err_set_field.field_name->data.symbol_expr.symbol); - fprintf(ar->f, ",\n"); - break; - default: - zig_unreachable(); - } - } - - ar->indent -= ar->indent_size; - print_indent(ar); - fprintf(ar->f, "}"); - break; - } - case NodeTypeResume: - { - fprintf(ar->f, "resume "); - render_node_grouped(ar, node->data.resume_expr.expr); - break; - } - case NodeTypeAwaitExpr: - { - fprintf(ar->f, "await "); - render_node_grouped(ar, node->data.await_expr.expr); - break; - } - case NodeTypeSuspend: - { - if (node->data.suspend.block != nullptr) { - fprintf(ar->f, "suspend "); - render_node_grouped(ar, node->data.suspend.block); - } else { - fprintf(ar->f, "suspend\n"); - } - break; - } - case NodeTypeEnumLiteral: - { - fprintf(ar->f, ".%s", buf_ptr(&node->data.enum_literal.identifier->data.str_lit.str)); - break; - } - case NodeTypeAnyTypeField: { - fprintf(ar->f, "anytype"); - break; - } - case NodeTypeParamDecl: - case NodeTypeTestDecl: - case NodeTypeStructField: - case NodeTypeUsingNamespace: - case NodeTypeErrorSetField: - zig_panic("TODO more ast rendering"); - } -} - - -void ast_render(FILE *f, AstNode *node, int indent_size) { - AstRender ar = {0}; - ar.f = f; - ar.indent_size = indent_size; - ar.indent = 0; - - render_node_grouped(&ar, node); -} - -void AstNode::src() { - fprintf(stderr, "%s:%" ZIG_PRI_usize ":%" ZIG_PRI_usize "\n", - buf_ptr(this->owner->data.structure.root_struct->path), - this->line + 1, this->column + 1); -} diff --git a/src/stage1/ast_render.hpp b/src/stage1/ast_render.hpp deleted file mode 100644 index cf70b04694..0000000000 --- a/src/stage1/ast_render.hpp +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (c) 2015 Andrew Kelley - * - * This file is part of zig, which is MIT licensed. - * See http://opensource.org/licenses/MIT - */ - -#ifndef ZIG_AST_RENDER_HPP -#define ZIG_AST_RENDER_HPP - -#include "all_types.hpp" -#include "parser.hpp" - -#include - -void ast_print(FILE *f, AstNode *node, int indent); - -void ast_render(FILE *f, AstNode *node, int indent_size); - -#endif diff --git a/src/stage1/astgen.cpp b/src/stage1/astgen.cpp new file mode 100644 index 0000000000..94ade4bebc --- /dev/null +++ b/src/stage1/astgen.cpp @@ -0,0 +1,8120 @@ +/* + * Copyright (c) 2021 Andrew Kelley + * + * This file is part of zig, which is MIT licensed. + * See http://opensource.org/licenses/MIT + */ + +#include "astgen.hpp" +#include "analyze.hpp" +#include "util.hpp" +#include "os.hpp" +#include "parser.hpp" + +static IrInstSrc *ir_gen_node(IrBuilderSrc *irb, AstNode *node, Scope *scope); +static IrInstSrc *ir_gen_node_extra(IrBuilderSrc *irb, AstNode *node, Scope *scope, LVal lval, + ResultLoc *result_loc); + +static IrInstSrc *ir_lval_wrap(IrBuilderSrc *irb, Scope *scope, IrInstSrc *value, LVal lval, + ResultLoc *result_loc); +static IrInstSrc *ir_expr_wrap(IrBuilderSrc *irb, Scope *scope, IrInstSrc *inst, + ResultLoc *result_loc); +static IrInstSrc *ir_gen_union_init_expr(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *union_type, IrInstSrc *field_name, AstNode *expr_node, + LVal lval, ResultLoc *parent_result_loc); +static ResultLocCast *ir_build_cast_result_loc(IrBuilderSrc *irb, IrInstSrc *dest_type, + ResultLoc *parent_result_loc); +static ZigVar *ir_create_var(IrBuilderSrc *irb, AstNode *node, Scope *scope, Buf *name, + bool src_is_const, bool gen_is_const, bool is_shadowable, IrInstSrc *is_comptime); +static void build_decl_var_and_init(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + ZigVar *var, IrInstSrc *init, const char *name_hint, IrInstSrc *is_comptime); + +static void ir_assert_impl(bool ok, IrInst *source_instruction, char const *file, unsigned int line) { + if (ok) return; + src_assert_impl(ok, source_instruction->source_node, file, line); +} + +static void ir_add_call_stack_errors(CodeGen *codegen, IrExecutableSrc *exec, ErrorMsg *err_msg, int limit) { + if (!exec || !exec->source_node || limit < 0) return; + add_error_note(codegen, err_msg, exec->source_node, buf_sprintf("called from here")); + + ir_add_call_stack_errors_gen(codegen, exec->parent_exec, err_msg, limit - 1); +} + +static ErrorMsg *exec_add_error_node(CodeGen *codegen, IrExecutableSrc *exec, AstNode *source_node, Buf *msg) { + ErrorMsg *err_msg = add_node_error(codegen, source_node, msg); + invalidate_exec(exec, err_msg); + if (exec->parent_exec) { + ir_add_call_stack_errors(codegen, exec, err_msg, 10); + } + return err_msg; +} + + +#define ir_assert(OK, SOURCE_INSTRUCTION) ir_assert_impl((OK), (SOURCE_INSTRUCTION), __FILE__, __LINE__) + + +static bool instr_is_unreachable(IrInstSrc *instruction) { + return instruction->is_noreturn; +} + +void destroy_instruction_src(IrInstSrc *inst) { + switch (inst->id) { + case IrInstSrcIdInvalid: + zig_unreachable(); + case IrInstSrcIdReturn: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdConst: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdBinOp: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdMergeErrSets: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdDeclVar: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdCall: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdCallExtra: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdAsyncCallExtra: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdUnOp: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdCondBr: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdBr: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdPhi: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdContainerInitList: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdContainerInitFields: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdUnreachable: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdElemPtr: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdVarPtr: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdLoadPtr: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdStorePtr: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdTypeOf: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdFieldPtr: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdSetCold: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdSetRuntimeSafety: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdSetFloatMode: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdArrayType: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdSliceType: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdAnyFrameType: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdAsm: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdSizeOf: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdTestNonNull: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdOptionalUnwrapPtr: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdPopCount: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdClz: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdCtz: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdBswap: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdBitReverse: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdSwitchBr: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdSwitchVar: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdSwitchElseVar: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdSwitchTarget: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdImport: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdRef: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdCompileErr: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdCompileLog: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdErrName: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdCImport: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdCInclude: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdCDefine: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdCUndef: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdEmbedFile: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdCmpxchg: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdFence: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdReduce: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdTruncate: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdIntCast: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdFloatCast: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdErrSetCast: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdIntToFloat: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdFloatToInt: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdBoolToInt: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdVectorType: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdShuffleVector: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdSplat: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdBoolNot: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdMemset: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdMemcpy: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdSlice: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdBreakpoint: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdReturnAddress: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdFrameAddress: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdFrameHandle: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdFrameType: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdFrameSize: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdAlignOf: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdOverflowOp: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdTestErr: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdUnwrapErrCode: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdUnwrapErrPayload: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdFnProto: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdTestComptime: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdPtrCast: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdBitCast: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdPtrToInt: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdIntToPtr: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdIntToEnum: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdIntToErr: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdErrToInt: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdCheckSwitchProngsUnderNo: + case IrInstSrcIdCheckSwitchProngsUnderYes: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdCheckStatementIsVoid: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdTypeName: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdTagName: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdPtrType: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdPtrTypeSimple: + case IrInstSrcIdPtrTypeSimpleConst: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdDeclRef: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdPanic: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdFieldParentPtr: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdByteOffsetOf: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdBitOffsetOf: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdTypeInfo: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdType: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdHasField: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdSetEvalBranchQuota: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdAlignCast: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdImplicitCast: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdResolveResult: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdResetResult: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdSetAlignStack: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdArgTypeAllowVarFalse: + case IrInstSrcIdArgTypeAllowVarTrue: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdExport: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdExtern: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdErrorReturnTrace: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdErrorUnion: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdAtomicRmw: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdSaveErrRetAddr: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdAddImplicitReturnType: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdFloatOp: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdMulAdd: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdAtomicLoad: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdAtomicStore: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdEnumToInt: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdCheckRuntimeScope: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdHasDecl: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdUndeclaredIdent: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdAlloca: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdEndExpr: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdUnionInitNamedField: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdSuspendBegin: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdSuspendFinish: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdResume: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdAwait: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdSpillBegin: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdSpillEnd: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdCallArgs: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdWasmMemorySize: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdWasmMemoryGrow: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdSrc: + return heap::c_allocator.destroy(reinterpret_cast(inst)); + } + zig_unreachable(); +} + + +bool ir_should_inline(IrExecutableSrc *exec, Scope *scope) { + if (exec->is_inline) + return true; + + while (scope != nullptr) { + if (scope->id == ScopeIdCompTime) + return true; + if (scope->id == ScopeIdTypeOf) + return false; + if (scope->id == ScopeIdFnDef) + break; + scope = scope->parent; + } + return false; +} + +static void ir_instruction_append(IrBasicBlockSrc *basic_block, IrInstSrc *instruction) { + assert(basic_block); + assert(instruction); + basic_block->instruction_list.append(instruction); +} + +static size_t exec_next_debug_id(IrExecutableSrc *exec) { + size_t result = exec->next_debug_id; + exec->next_debug_id += 1; + return result; +} + +static ZigFn *exec_fn_entry(IrExecutableSrc *exec) { + return exec->fn_entry; +} + +static Buf *exec_c_import_buf(IrExecutableSrc *exec) { + return exec->c_import_buf; +} + +static void ir_ref_bb(IrBasicBlockSrc *bb) { + bb->ref_count += 1; +} + +static void ir_ref_instruction(IrInstSrc *instruction, IrBasicBlockSrc *cur_bb) { + assert(instruction->id != IrInstSrcIdInvalid); + instruction->base.ref_count += 1; + if (instruction->owner_bb != cur_bb && !instr_is_unreachable(instruction) + && instruction->id != IrInstSrcIdConst) + { + ir_ref_bb(instruction->owner_bb); + } +} + +static IrBasicBlockSrc *ir_create_basic_block(IrBuilderSrc *irb, Scope *scope, const char *name_hint) { + IrBasicBlockSrc *result = heap::c_allocator.create(); + result->scope = scope; + result->name_hint = name_hint; + result->debug_id = exec_next_debug_id(irb->exec); + result->index = UINT32_MAX; // set later + return result; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcDeclVar *) { + return IrInstSrcIdDeclVar; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcBr *) { + return IrInstSrcIdBr; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcCondBr *) { + return IrInstSrcIdCondBr; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcSwitchBr *) { + return IrInstSrcIdSwitchBr; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcSwitchVar *) { + return IrInstSrcIdSwitchVar; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcSwitchElseVar *) { + return IrInstSrcIdSwitchElseVar; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcSwitchTarget *) { + return IrInstSrcIdSwitchTarget; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcPhi *) { + return IrInstSrcIdPhi; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcUnOp *) { + return IrInstSrcIdUnOp; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcBinOp *) { + return IrInstSrcIdBinOp; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcMergeErrSets *) { + return IrInstSrcIdMergeErrSets; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcLoadPtr *) { + return IrInstSrcIdLoadPtr; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcStorePtr *) { + return IrInstSrcIdStorePtr; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcFieldPtr *) { + return IrInstSrcIdFieldPtr; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcElemPtr *) { + return IrInstSrcIdElemPtr; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcVarPtr *) { + return IrInstSrcIdVarPtr; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcCall *) { + return IrInstSrcIdCall; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcCallArgs *) { + return IrInstSrcIdCallArgs; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcCallExtra *) { + return IrInstSrcIdCallExtra; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcAsyncCallExtra *) { + return IrInstSrcIdAsyncCallExtra; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcConst *) { + return IrInstSrcIdConst; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcReturn *) { + return IrInstSrcIdReturn; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcContainerInitList *) { + return IrInstSrcIdContainerInitList; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcContainerInitFields *) { + return IrInstSrcIdContainerInitFields; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcUnreachable *) { + return IrInstSrcIdUnreachable; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcTypeOf *) { + return IrInstSrcIdTypeOf; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcSetCold *) { + return IrInstSrcIdSetCold; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcSetRuntimeSafety *) { + return IrInstSrcIdSetRuntimeSafety; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcSetFloatMode *) { + return IrInstSrcIdSetFloatMode; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcArrayType *) { + return IrInstSrcIdArrayType; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcAnyFrameType *) { + return IrInstSrcIdAnyFrameType; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcSliceType *) { + return IrInstSrcIdSliceType; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcAsm *) { + return IrInstSrcIdAsm; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcSizeOf *) { + return IrInstSrcIdSizeOf; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcTestNonNull *) { + return IrInstSrcIdTestNonNull; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcOptionalUnwrapPtr *) { + return IrInstSrcIdOptionalUnwrapPtr; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcClz *) { + return IrInstSrcIdClz; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcCtz *) { + return IrInstSrcIdCtz; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcPopCount *) { + return IrInstSrcIdPopCount; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcBswap *) { + return IrInstSrcIdBswap; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcBitReverse *) { + return IrInstSrcIdBitReverse; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcImport *) { + return IrInstSrcIdImport; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcCImport *) { + return IrInstSrcIdCImport; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcCInclude *) { + return IrInstSrcIdCInclude; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcCDefine *) { + return IrInstSrcIdCDefine; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcCUndef *) { + return IrInstSrcIdCUndef; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcRef *) { + return IrInstSrcIdRef; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcCompileErr *) { + return IrInstSrcIdCompileErr; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcCompileLog *) { + return IrInstSrcIdCompileLog; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcErrName *) { + return IrInstSrcIdErrName; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcEmbedFile *) { + return IrInstSrcIdEmbedFile; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcCmpxchg *) { + return IrInstSrcIdCmpxchg; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcFence *) { + return IrInstSrcIdFence; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcReduce *) { + return IrInstSrcIdReduce; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcTruncate *) { + return IrInstSrcIdTruncate; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcIntCast *) { + return IrInstSrcIdIntCast; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcFloatCast *) { + return IrInstSrcIdFloatCast; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcIntToFloat *) { + return IrInstSrcIdIntToFloat; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcFloatToInt *) { + return IrInstSrcIdFloatToInt; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcBoolToInt *) { + return IrInstSrcIdBoolToInt; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcVectorType *) { + return IrInstSrcIdVectorType; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcShuffleVector *) { + return IrInstSrcIdShuffleVector; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcSplat *) { + return IrInstSrcIdSplat; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcBoolNot *) { + return IrInstSrcIdBoolNot; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcMemset *) { + return IrInstSrcIdMemset; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcMemcpy *) { + return IrInstSrcIdMemcpy; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcSlice *) { + return IrInstSrcIdSlice; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcBreakpoint *) { + return IrInstSrcIdBreakpoint; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcReturnAddress *) { + return IrInstSrcIdReturnAddress; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcFrameAddress *) { + return IrInstSrcIdFrameAddress; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcFrameHandle *) { + return IrInstSrcIdFrameHandle; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcFrameType *) { + return IrInstSrcIdFrameType; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcFrameSize *) { + return IrInstSrcIdFrameSize; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcAlignOf *) { + return IrInstSrcIdAlignOf; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcOverflowOp *) { + return IrInstSrcIdOverflowOp; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcTestErr *) { + return IrInstSrcIdTestErr; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcMulAdd *) { + return IrInstSrcIdMulAdd; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcFloatOp *) { + return IrInstSrcIdFloatOp; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcUnwrapErrCode *) { + return IrInstSrcIdUnwrapErrCode; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcUnwrapErrPayload *) { + return IrInstSrcIdUnwrapErrPayload; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcFnProto *) { + return IrInstSrcIdFnProto; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcTestComptime *) { + return IrInstSrcIdTestComptime; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcPtrCast *) { + return IrInstSrcIdPtrCast; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcBitCast *) { + return IrInstSrcIdBitCast; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcIntToPtr *) { + return IrInstSrcIdIntToPtr; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcPtrToInt *) { + return IrInstSrcIdPtrToInt; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcIntToEnum *) { + return IrInstSrcIdIntToEnum; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcEnumToInt *) { + return IrInstSrcIdEnumToInt; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcIntToErr *) { + return IrInstSrcIdIntToErr; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcErrToInt *) { + return IrInstSrcIdErrToInt; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcCheckStatementIsVoid *) { + return IrInstSrcIdCheckStatementIsVoid; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcTypeName *) { + return IrInstSrcIdTypeName; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcDeclRef *) { + return IrInstSrcIdDeclRef; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcPanic *) { + return IrInstSrcIdPanic; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcTagName *) { + return IrInstSrcIdTagName; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcFieldParentPtr *) { + return IrInstSrcIdFieldParentPtr; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcByteOffsetOf *) { + return IrInstSrcIdByteOffsetOf; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcBitOffsetOf *) { + return IrInstSrcIdBitOffsetOf; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcTypeInfo *) { + return IrInstSrcIdTypeInfo; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcType *) { + return IrInstSrcIdType; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcHasField *) { + return IrInstSrcIdHasField; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcSetEvalBranchQuota *) { + return IrInstSrcIdSetEvalBranchQuota; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcPtrType *) { + return IrInstSrcIdPtrType; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcAlignCast *) { + return IrInstSrcIdAlignCast; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcImplicitCast *) { + return IrInstSrcIdImplicitCast; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcResolveResult *) { + return IrInstSrcIdResolveResult; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcResetResult *) { + return IrInstSrcIdResetResult; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcSetAlignStack *) { + return IrInstSrcIdSetAlignStack; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcExport *) { + return IrInstSrcIdExport; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcExtern *) { + return IrInstSrcIdExtern; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcErrorReturnTrace *) { + return IrInstSrcIdErrorReturnTrace; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcErrorUnion *) { + return IrInstSrcIdErrorUnion; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcAtomicRmw *) { + return IrInstSrcIdAtomicRmw; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcAtomicLoad *) { + return IrInstSrcIdAtomicLoad; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcAtomicStore *) { + return IrInstSrcIdAtomicStore; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcSaveErrRetAddr *) { + return IrInstSrcIdSaveErrRetAddr; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcAddImplicitReturnType *) { + return IrInstSrcIdAddImplicitReturnType; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcErrSetCast *) { + return IrInstSrcIdErrSetCast; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcCheckRuntimeScope *) { + return IrInstSrcIdCheckRuntimeScope; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcHasDecl *) { + return IrInstSrcIdHasDecl; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcUndeclaredIdent *) { + return IrInstSrcIdUndeclaredIdent; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcAlloca *) { + return IrInstSrcIdAlloca; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcEndExpr *) { + return IrInstSrcIdEndExpr; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcUnionInitNamedField *) { + return IrInstSrcIdUnionInitNamedField; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcSuspendBegin *) { + return IrInstSrcIdSuspendBegin; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcSuspendFinish *) { + return IrInstSrcIdSuspendFinish; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcAwait *) { + return IrInstSrcIdAwait; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcResume *) { + return IrInstSrcIdResume; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcSpillBegin *) { + return IrInstSrcIdSpillBegin; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcSpillEnd *) { + return IrInstSrcIdSpillEnd; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcWasmMemorySize *) { + return IrInstSrcIdWasmMemorySize; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcWasmMemoryGrow *) { + return IrInstSrcIdWasmMemoryGrow; +} + +static constexpr IrInstSrcId ir_inst_id(IrInstSrcSrc *) { + return IrInstSrcIdSrc; +} + +template +static T *ir_create_instruction(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { + T *special_instruction = heap::c_allocator.create(); + special_instruction->base.id = ir_inst_id(special_instruction); + special_instruction->base.base.scope = scope; + special_instruction->base.base.source_node = source_node; + special_instruction->base.base.debug_id = exec_next_debug_id(irb->exec); + special_instruction->base.owner_bb = irb->current_basic_block; + return special_instruction; +} + +template +static T *ir_build_instruction(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { + T *special_instruction = ir_create_instruction(irb, scope, source_node); + ir_instruction_append(irb->current_basic_block, &special_instruction->base); + return special_instruction; +} + +static IrInstSrc *ir_build_cond_br(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *condition, + IrBasicBlockSrc *then_block, IrBasicBlockSrc *else_block, IrInstSrc *is_comptime) +{ + IrInstSrcCondBr *inst = ir_build_instruction(irb, scope, source_node); + inst->base.is_noreturn = true; + inst->condition = condition; + inst->then_block = then_block; + inst->else_block = else_block; + inst->is_comptime = is_comptime; + + ir_ref_instruction(condition, irb->current_basic_block); + ir_ref_bb(then_block); + ir_ref_bb(else_block); + if (is_comptime != nullptr) ir_ref_instruction(is_comptime, irb->current_basic_block); + + return &inst->base; +} + +static IrInstSrc *ir_build_return_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *operand) { + IrInstSrcReturn *inst = ir_build_instruction(irb, scope, source_node); + inst->base.is_noreturn = true; + inst->operand = operand; + + if (operand != nullptr) ir_ref_instruction(operand, irb->current_basic_block); + + return &inst->base; +} + +static IrInstSrc *ir_build_const_void(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { + IrInstSrcConst *const_instruction = ir_create_instruction(irb, scope, source_node); + ir_instruction_append(irb->current_basic_block, &const_instruction->base); + const_instruction->value = irb->codegen->intern.for_void(); + return &const_instruction->base; +} + +static IrInstSrc *ir_build_const_undefined(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { + IrInstSrcConst *const_instruction = ir_create_instruction(irb, scope, source_node); + ir_instruction_append(irb->current_basic_block, &const_instruction->base); + const_instruction->value = irb->codegen->intern.for_undefined(); + const_instruction->value->special = ConstValSpecialUndef; + return &const_instruction->base; +} + +static IrInstSrc *ir_build_const_uint(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, uint64_t value) { + IrInstSrcConst *const_instruction = ir_build_instruction(irb, scope, source_node); + const_instruction->value = irb->codegen->pass1_arena->create(); + const_instruction->value->type = irb->codegen->builtin_types.entry_num_lit_int; + const_instruction->value->special = ConstValSpecialStatic; + bigint_init_unsigned(&const_instruction->value->data.x_bigint, value); + return &const_instruction->base; +} + +static IrInstSrc *ir_build_const_bigint(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + BigInt bigint) +{ + IrInstSrcConst *const_instruction = ir_build_instruction(irb, scope, source_node); + const_instruction->value = irb->codegen->pass1_arena->create(); + const_instruction->value->type = irb->codegen->builtin_types.entry_num_lit_int; + const_instruction->value->special = ConstValSpecialStatic; + const_instruction->value->data.x_bigint = bigint; + return &const_instruction->base; +} + +static IrInstSrc *ir_build_const_bigfloat(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + BigFloat bigfloat) +{ + IrInstSrcConst *const_instruction = ir_build_instruction(irb, scope, source_node); + const_instruction->value = irb->codegen->pass1_arena->create(); + const_instruction->value->type = irb->codegen->builtin_types.entry_num_lit_float; + const_instruction->value->special = ConstValSpecialStatic; + const_instruction->value->data.x_bigfloat = bigfloat; + return &const_instruction->base; +} + +static IrInstSrc *ir_build_const_null(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { + IrInstSrcConst *const_instruction = ir_create_instruction(irb, scope, source_node); + ir_instruction_append(irb->current_basic_block, &const_instruction->base); + const_instruction->value = irb->codegen->intern.for_null(); + return &const_instruction->base; +} + +static IrInstSrc *ir_build_const_usize(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, uint64_t value) { + IrInstSrcConst *const_instruction = ir_build_instruction(irb, scope, source_node); + const_instruction->value = irb->codegen->pass1_arena->create(); + const_instruction->value->type = irb->codegen->builtin_types.entry_usize; + const_instruction->value->special = ConstValSpecialStatic; + bigint_init_unsigned(&const_instruction->value->data.x_bigint, value); + return &const_instruction->base; +} + +static IrInstSrc *ir_create_const_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + ZigType *type_entry) +{ + IrInstSrcConst *const_instruction = ir_create_instruction(irb, scope, source_node); + const_instruction->value = irb->codegen->pass1_arena->create(); + const_instruction->value->type = irb->codegen->builtin_types.entry_type; + const_instruction->value->special = ConstValSpecialStatic; + const_instruction->value->data.x_type = type_entry; + return &const_instruction->base; +} + +static IrInstSrc *ir_build_const_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + ZigType *type_entry) +{ + IrInstSrc *instruction = ir_create_const_type(irb, scope, source_node, type_entry); + ir_instruction_append(irb->current_basic_block, instruction); + return instruction; +} + +static IrInstSrc *ir_build_const_import(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, ZigType *import) { + IrInstSrcConst *const_instruction = ir_build_instruction(irb, scope, source_node); + const_instruction->value = irb->codegen->pass1_arena->create(); + const_instruction->value->type = irb->codegen->builtin_types.entry_type; + const_instruction->value->special = ConstValSpecialStatic; + const_instruction->value->data.x_type = import; + return &const_instruction->base; +} + +static IrInstSrc *ir_build_const_bool(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, bool value) { + IrInstSrcConst *const_instruction = ir_build_instruction(irb, scope, source_node); + const_instruction->value = irb->codegen->pass1_arena->create(); + const_instruction->value->type = irb->codegen->builtin_types.entry_bool; + const_instruction->value->special = ConstValSpecialStatic; + const_instruction->value->data.x_bool = value; + return &const_instruction->base; +} + +static IrInstSrc *ir_build_const_enum_literal(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, Buf *name) { + IrInstSrcConst *const_instruction = ir_build_instruction(irb, scope, source_node); + const_instruction->value = irb->codegen->pass1_arena->create(); + const_instruction->value->type = irb->codegen->builtin_types.entry_enum_literal; + const_instruction->value->special = ConstValSpecialStatic; + const_instruction->value->data.x_enum_literal = name; + return &const_instruction->base; +} + +// Consumes `str`. +static IrInstSrc *ir_create_const_str_lit(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, Buf *str) { + IrInstSrcConst *const_instruction = ir_create_instruction(irb, scope, source_node); + const_instruction->value = irb->codegen->pass1_arena->create(); + init_const_str_lit(irb->codegen, const_instruction->value, str, true); + + return &const_instruction->base; +} + +// Consumes `str`. +static IrInstSrc *ir_build_const_str_lit(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, Buf *str) { + IrInstSrc *instruction = ir_create_const_str_lit(irb, scope, source_node, str); + ir_instruction_append(irb->current_basic_block, instruction); + return instruction; +} + +static IrInstSrc *ir_build_bin_op(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrBinOp op_id, + IrInstSrc *op1, IrInstSrc *op2, bool safety_check_on) +{ + IrInstSrcBinOp *inst = ir_build_instruction(irb, scope, source_node); + inst->op_id = op_id; + inst->op1 = op1; + inst->op2 = op2; + inst->safety_check_on = safety_check_on; + + ir_ref_instruction(op1, irb->current_basic_block); + ir_ref_instruction(op2, irb->current_basic_block); + + return &inst->base; +} + +static IrInstSrc *ir_build_merge_err_sets(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *op1, IrInstSrc *op2, Buf *type_name) +{ + IrInstSrcMergeErrSets *inst = ir_build_instruction(irb, scope, source_node); + inst->op1 = op1; + inst->op2 = op2; + inst->type_name = type_name; + + ir_ref_instruction(op1, irb->current_basic_block); + ir_ref_instruction(op2, irb->current_basic_block); + + return &inst->base; +} + +static IrInstSrc *ir_build_var_ptr_x(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, ZigVar *var, + ScopeFnDef *crossed_fndef_scope) +{ + IrInstSrcVarPtr *instruction = ir_build_instruction(irb, scope, source_node); + instruction->var = var; + instruction->crossed_fndef_scope = crossed_fndef_scope; + + var->ref_count += 1; + + return &instruction->base; +} + +static IrInstSrc *ir_build_var_ptr(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, ZigVar *var) { + return ir_build_var_ptr_x(irb, scope, source_node, var, nullptr); +} + +static IrInstSrc *ir_build_elem_ptr(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *array_ptr, IrInstSrc *elem_index, bool safety_check_on, PtrLen ptr_len, + AstNode *init_array_type_source_node) +{ + IrInstSrcElemPtr *instruction = ir_build_instruction(irb, scope, source_node); + instruction->array_ptr = array_ptr; + instruction->elem_index = elem_index; + instruction->safety_check_on = safety_check_on; + instruction->ptr_len = ptr_len; + instruction->init_array_type_source_node = init_array_type_source_node; + + ir_ref_instruction(array_ptr, irb->current_basic_block); + ir_ref_instruction(elem_index, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_field_ptr_instruction(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *container_ptr, IrInstSrc *field_name_expr, bool initializing) +{ + IrInstSrcFieldPtr *instruction = ir_build_instruction(irb, scope, source_node); + instruction->container_ptr = container_ptr; + instruction->field_name_buffer = nullptr; + instruction->field_name_expr = field_name_expr; + instruction->initializing = initializing; + + ir_ref_instruction(container_ptr, irb->current_basic_block); + ir_ref_instruction(field_name_expr, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_field_ptr(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *container_ptr, Buf *field_name, bool initializing) +{ + IrInstSrcFieldPtr *instruction = ir_build_instruction(irb, scope, source_node); + instruction->container_ptr = container_ptr; + instruction->field_name_buffer = field_name; + instruction->field_name_expr = nullptr; + instruction->initializing = initializing; + + ir_ref_instruction(container_ptr, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_has_field(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *container_type, IrInstSrc *field_name) +{ + IrInstSrcHasField *instruction = ir_build_instruction(irb, scope, source_node); + instruction->container_type = container_type; + instruction->field_name = field_name; + + ir_ref_instruction(container_type, irb->current_basic_block); + ir_ref_instruction(field_name, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_call_extra(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *options, IrInstSrc *fn_ref, IrInstSrc *args, ResultLoc *result_loc) +{ + IrInstSrcCallExtra *call_instruction = ir_build_instruction(irb, scope, source_node); + call_instruction->options = options; + call_instruction->fn_ref = fn_ref; + call_instruction->args = args; + call_instruction->result_loc = result_loc; + + ir_ref_instruction(options, irb->current_basic_block); + ir_ref_instruction(fn_ref, irb->current_basic_block); + ir_ref_instruction(args, irb->current_basic_block); + + return &call_instruction->base; +} + +static IrInstSrc *ir_build_async_call_extra(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + CallModifier modifier, IrInstSrc *fn_ref, IrInstSrc *ret_ptr, IrInstSrc *new_stack, IrInstSrc *args, ResultLoc *result_loc) +{ + IrInstSrcAsyncCallExtra *call_instruction = ir_build_instruction(irb, scope, source_node); + call_instruction->modifier = modifier; + call_instruction->fn_ref = fn_ref; + call_instruction->ret_ptr = ret_ptr; + call_instruction->new_stack = new_stack; + call_instruction->args = args; + call_instruction->result_loc = result_loc; + + ir_ref_instruction(fn_ref, irb->current_basic_block); + if (ret_ptr != nullptr) ir_ref_instruction(ret_ptr, irb->current_basic_block); + ir_ref_instruction(new_stack, irb->current_basic_block); + ir_ref_instruction(args, irb->current_basic_block); + + return &call_instruction->base; +} + +static IrInstSrc *ir_build_call_args(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *options, IrInstSrc *fn_ref, IrInstSrc **args_ptr, size_t args_len, + ResultLoc *result_loc) +{ + IrInstSrcCallArgs *call_instruction = ir_build_instruction(irb, scope, source_node); + call_instruction->options = options; + call_instruction->fn_ref = fn_ref; + call_instruction->args_ptr = args_ptr; + call_instruction->args_len = args_len; + call_instruction->result_loc = result_loc; + + ir_ref_instruction(options, irb->current_basic_block); + ir_ref_instruction(fn_ref, irb->current_basic_block); + for (size_t i = 0; i < args_len; i += 1) + ir_ref_instruction(args_ptr[i], irb->current_basic_block); + + return &call_instruction->base; +} + +static IrInstSrc *ir_build_call_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + ZigFn *fn_entry, IrInstSrc *fn_ref, size_t arg_count, IrInstSrc **args, + IrInstSrc *ret_ptr, CallModifier modifier, bool is_async_call_builtin, + IrInstSrc *new_stack, ResultLoc *result_loc) +{ + IrInstSrcCall *call_instruction = ir_build_instruction(irb, scope, source_node); + call_instruction->fn_entry = fn_entry; + call_instruction->fn_ref = fn_ref; + call_instruction->args = args; + call_instruction->arg_count = arg_count; + call_instruction->modifier = modifier; + call_instruction->is_async_call_builtin = is_async_call_builtin; + call_instruction->new_stack = new_stack; + call_instruction->result_loc = result_loc; + call_instruction->ret_ptr = ret_ptr; + + if (fn_ref != nullptr) ir_ref_instruction(fn_ref, irb->current_basic_block); + for (size_t i = 0; i < arg_count; i += 1) + ir_ref_instruction(args[i], irb->current_basic_block); + if (ret_ptr != nullptr) ir_ref_instruction(ret_ptr, irb->current_basic_block); + if (new_stack != nullptr) ir_ref_instruction(new_stack, irb->current_basic_block); + + return &call_instruction->base; +} + +static IrInstSrc *ir_build_phi(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + size_t incoming_count, IrBasicBlockSrc **incoming_blocks, IrInstSrc **incoming_values, + ResultLocPeerParent *peer_parent) +{ + assert(incoming_count != 0); + assert(incoming_count != SIZE_MAX); + + IrInstSrcPhi *phi_instruction = ir_build_instruction(irb, scope, source_node); + phi_instruction->incoming_count = incoming_count; + phi_instruction->incoming_blocks = incoming_blocks; + phi_instruction->incoming_values = incoming_values; + phi_instruction->peer_parent = peer_parent; + + for (size_t i = 0; i < incoming_count; i += 1) { + ir_ref_bb(incoming_blocks[i]); + ir_ref_instruction(incoming_values[i], irb->current_basic_block); + } + + return &phi_instruction->base; +} + +static IrInstSrc *ir_build_br(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrBasicBlockSrc *dest_block, IrInstSrc *is_comptime) +{ + IrInstSrcBr *inst = ir_build_instruction(irb, scope, source_node); + inst->base.is_noreturn = true; + inst->dest_block = dest_block; + inst->is_comptime = is_comptime; + + ir_ref_bb(dest_block); + if (is_comptime) ir_ref_instruction(is_comptime, irb->current_basic_block); + + return &inst->base; +} + +static IrInstSrc *ir_build_ptr_type_simple(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *child_type, bool is_const) +{ + IrInstSrcPtrTypeSimple *inst = heap::c_allocator.create(); + inst->base.id = is_const ? IrInstSrcIdPtrTypeSimpleConst : IrInstSrcIdPtrTypeSimple; + inst->base.base.scope = scope; + inst->base.base.source_node = source_node; + inst->base.base.debug_id = exec_next_debug_id(irb->exec); + inst->base.owner_bb = irb->current_basic_block; + ir_instruction_append(irb->current_basic_block, &inst->base); + + inst->child_type = child_type; + + ir_ref_instruction(child_type, irb->current_basic_block); + + return &inst->base; +} + +static IrInstSrc *ir_build_ptr_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *child_type, bool is_const, bool is_volatile, PtrLen ptr_len, + IrInstSrc *sentinel, IrInstSrc *align_value, + uint32_t bit_offset_start, uint32_t host_int_bytes, bool is_allow_zero) +{ + if (!is_volatile && ptr_len == PtrLenSingle && sentinel == nullptr && align_value == nullptr && + bit_offset_start == 0 && host_int_bytes == 0 && is_allow_zero == 0) + { + return ir_build_ptr_type_simple(irb, scope, source_node, child_type, is_const); + } + + IrInstSrcPtrType *inst = ir_build_instruction(irb, scope, source_node); + inst->sentinel = sentinel; + inst->align_value = align_value; + inst->child_type = child_type; + inst->is_const = is_const; + inst->is_volatile = is_volatile; + inst->ptr_len = ptr_len; + inst->bit_offset_start = bit_offset_start; + inst->host_int_bytes = host_int_bytes; + inst->is_allow_zero = is_allow_zero; + + if (sentinel) ir_ref_instruction(sentinel, irb->current_basic_block); + if (align_value) ir_ref_instruction(align_value, irb->current_basic_block); + ir_ref_instruction(child_type, irb->current_basic_block); + + return &inst->base; +} + +static IrInstSrc *ir_build_un_op_lval(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrUnOp op_id, + IrInstSrc *value, LVal lval, ResultLoc *result_loc) +{ + IrInstSrcUnOp *instruction = ir_build_instruction(irb, scope, source_node); + instruction->op_id = op_id; + instruction->value = value; + instruction->lval = lval; + instruction->result_loc = result_loc; + + ir_ref_instruction(value, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_un_op(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrUnOp op_id, + IrInstSrc *value) +{ + return ir_build_un_op_lval(irb, scope, source_node, op_id, value, LValNone, nullptr); +} + +static IrInstSrc *ir_build_container_init_list(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + size_t item_count, IrInstSrc **elem_result_loc_list, IrInstSrc *result_loc, + AstNode *init_array_type_source_node) +{ + IrInstSrcContainerInitList *container_init_list_instruction = + ir_build_instruction(irb, scope, source_node); + container_init_list_instruction->item_count = item_count; + container_init_list_instruction->elem_result_loc_list = elem_result_loc_list; + container_init_list_instruction->result_loc = result_loc; + container_init_list_instruction->init_array_type_source_node = init_array_type_source_node; + + for (size_t i = 0; i < item_count; i += 1) { + ir_ref_instruction(elem_result_loc_list[i], irb->current_basic_block); + } + if (result_loc != nullptr) ir_ref_instruction(result_loc, irb->current_basic_block); + + return &container_init_list_instruction->base; +} + +static IrInstSrc *ir_build_container_init_fields(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + size_t field_count, IrInstSrcContainerInitFieldsField *fields, IrInstSrc *result_loc) +{ + IrInstSrcContainerInitFields *container_init_fields_instruction = + ir_build_instruction(irb, scope, source_node); + container_init_fields_instruction->field_count = field_count; + container_init_fields_instruction->fields = fields; + container_init_fields_instruction->result_loc = result_loc; + + for (size_t i = 0; i < field_count; i += 1) { + ir_ref_instruction(fields[i].result_loc, irb->current_basic_block); + } + if (result_loc != nullptr) ir_ref_instruction(result_loc, irb->current_basic_block); + + return &container_init_fields_instruction->base; +} + +static IrInstSrc *ir_build_unreachable(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { + IrInstSrcUnreachable *inst = ir_build_instruction(irb, scope, source_node); + inst->base.is_noreturn = true; + return &inst->base; +} + +static IrInstSrcStorePtr *ir_build_store_ptr(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *ptr, IrInstSrc *value) +{ + IrInstSrcStorePtr *instruction = ir_build_instruction(irb, scope, source_node); + instruction->ptr = ptr; + instruction->value = value; + + ir_ref_instruction(ptr, irb->current_basic_block); + ir_ref_instruction(value, irb->current_basic_block); + + return instruction; +} + +static IrInstSrc *ir_build_var_decl_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + ZigVar *var, IrInstSrc *align_value, IrInstSrc *ptr) +{ + IrInstSrcDeclVar *inst = ir_build_instruction(irb, scope, source_node); + inst->var = var; + inst->align_value = align_value; + inst->ptr = ptr; + + if (align_value != nullptr) ir_ref_instruction(align_value, irb->current_basic_block); + ir_ref_instruction(ptr, irb->current_basic_block); + + return &inst->base; +} + +static IrInstSrc *ir_build_export(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *target, IrInstSrc *options) +{ + IrInstSrcExport *export_instruction = ir_build_instruction( + irb, scope, source_node); + export_instruction->target = target; + export_instruction->options = options; + + ir_ref_instruction(target, irb->current_basic_block); + ir_ref_instruction(options, irb->current_basic_block); + + return &export_instruction->base; +} + +static IrInstSrc *ir_build_extern(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *type, IrInstSrc *options) +{ + IrInstSrcExtern *extern_instruction = ir_build_instruction( + irb, scope, source_node); + extern_instruction->type = type; + extern_instruction->options = options; + + ir_ref_instruction(type, irb->current_basic_block); + ir_ref_instruction(options, irb->current_basic_block); + + return &extern_instruction->base; +} + +static IrInstSrc *ir_build_load_ptr(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *ptr) { + IrInstSrcLoadPtr *instruction = ir_build_instruction(irb, scope, source_node); + instruction->ptr = ptr; + + ir_ref_instruction(ptr, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_typeof_n(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc **values, size_t value_count) +{ + assert(value_count >= 2); + + IrInstSrcTypeOf *instruction = ir_build_instruction(irb, scope, source_node); + instruction->value.list = values; + instruction->value_count = value_count; + + for (size_t i = 0; i < value_count; i++) + ir_ref_instruction(values[i], irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_typeof_1(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *value) { + IrInstSrcTypeOf *instruction = ir_build_instruction(irb, scope, source_node); + instruction->value.scalar = value; + + ir_ref_instruction(value, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_set_cold(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *is_cold) { + IrInstSrcSetCold *instruction = ir_build_instruction(irb, scope, source_node); + instruction->is_cold = is_cold; + + ir_ref_instruction(is_cold, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_set_runtime_safety(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *safety_on) +{ + IrInstSrcSetRuntimeSafety *inst = ir_build_instruction(irb, scope, source_node); + inst->safety_on = safety_on; + + ir_ref_instruction(safety_on, irb->current_basic_block); + + return &inst->base; +} + +static IrInstSrc *ir_build_set_float_mode(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *mode_value) +{ + IrInstSrcSetFloatMode *instruction = ir_build_instruction(irb, scope, source_node); + instruction->mode_value = mode_value; + + ir_ref_instruction(mode_value, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_array_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *size, + IrInstSrc *sentinel, IrInstSrc *child_type) +{ + IrInstSrcArrayType *instruction = ir_build_instruction(irb, scope, source_node); + instruction->size = size; + instruction->sentinel = sentinel; + instruction->child_type = child_type; + + ir_ref_instruction(size, irb->current_basic_block); + if (sentinel != nullptr) ir_ref_instruction(sentinel, irb->current_basic_block); + ir_ref_instruction(child_type, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_anyframe_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *payload_type) +{ + IrInstSrcAnyFrameType *instruction = ir_build_instruction(irb, scope, source_node); + instruction->payload_type = payload_type; + + if (payload_type != nullptr) ir_ref_instruction(payload_type, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_slice_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *child_type, bool is_const, bool is_volatile, + IrInstSrc *sentinel, IrInstSrc *align_value, bool is_allow_zero) +{ + IrInstSrcSliceType *instruction = ir_build_instruction(irb, scope, source_node); + instruction->is_const = is_const; + instruction->is_volatile = is_volatile; + instruction->child_type = child_type; + instruction->sentinel = sentinel; + instruction->align_value = align_value; + instruction->is_allow_zero = is_allow_zero; + + if (sentinel != nullptr) ir_ref_instruction(sentinel, irb->current_basic_block); + if (align_value != nullptr) ir_ref_instruction(align_value, irb->current_basic_block); + ir_ref_instruction(child_type, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_asm_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *asm_template, IrInstSrc **input_list, IrInstSrc **output_types, + ZigVar **output_vars, size_t return_count, bool has_side_effects, bool is_global) +{ + IrInstSrcAsm *instruction = ir_build_instruction(irb, scope, source_node); + instruction->asm_template = asm_template; + instruction->input_list = input_list; + instruction->output_types = output_types; + instruction->output_vars = output_vars; + instruction->return_count = return_count; + instruction->has_side_effects = has_side_effects; + instruction->is_global = is_global; + + assert(source_node->type == NodeTypeAsmExpr); + for (size_t i = 0; i < source_node->data.asm_expr.output_list.length; i += 1) { + IrInstSrc *output_type = output_types[i]; + if (output_type) ir_ref_instruction(output_type, irb->current_basic_block); + } + + for (size_t i = 0; i < source_node->data.asm_expr.input_list.length; i += 1) { + IrInstSrc *input_value = input_list[i]; + ir_ref_instruction(input_value, irb->current_basic_block); + } + + return &instruction->base; +} + +static IrInstSrc *ir_build_size_of(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *type_value, + bool bit_size) +{ + IrInstSrcSizeOf *instruction = ir_build_instruction(irb, scope, source_node); + instruction->type_value = type_value; + instruction->bit_size = bit_size; + + ir_ref_instruction(type_value, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_test_non_null_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *value) +{ + IrInstSrcTestNonNull *instruction = ir_build_instruction(irb, scope, source_node); + instruction->value = value; + + ir_ref_instruction(value, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_optional_unwrap_ptr(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *base_ptr, bool safety_check_on) +{ + IrInstSrcOptionalUnwrapPtr *instruction = ir_build_instruction(irb, scope, source_node); + instruction->base_ptr = base_ptr; + instruction->safety_check_on = safety_check_on; + + ir_ref_instruction(base_ptr, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_clz(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *type, + IrInstSrc *op) +{ + IrInstSrcClz *instruction = ir_build_instruction(irb, scope, source_node); + instruction->type = type; + instruction->op = op; + + ir_ref_instruction(type, irb->current_basic_block); + ir_ref_instruction(op, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_ctz(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *type, + IrInstSrc *op) +{ + IrInstSrcCtz *instruction = ir_build_instruction(irb, scope, source_node); + instruction->type = type; + instruction->op = op; + + ir_ref_instruction(type, irb->current_basic_block); + ir_ref_instruction(op, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_pop_count(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *type, + IrInstSrc *op) +{ + IrInstSrcPopCount *instruction = ir_build_instruction(irb, scope, source_node); + instruction->type = type; + instruction->op = op; + + ir_ref_instruction(type, irb->current_basic_block); + ir_ref_instruction(op, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_bswap(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *type, + IrInstSrc *op) +{ + IrInstSrcBswap *instruction = ir_build_instruction(irb, scope, source_node); + instruction->type = type; + instruction->op = op; + + ir_ref_instruction(type, irb->current_basic_block); + ir_ref_instruction(op, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_bit_reverse(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *type, + IrInstSrc *op) +{ + IrInstSrcBitReverse *instruction = ir_build_instruction(irb, scope, source_node); + instruction->type = type; + instruction->op = op; + + ir_ref_instruction(type, irb->current_basic_block); + ir_ref_instruction(op, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrcSwitchBr *ir_build_switch_br_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *target_value, IrBasicBlockSrc *else_block, size_t case_count, IrInstSrcSwitchBrCase *cases, + IrInstSrc *is_comptime, IrInstSrc *switch_prongs_void) +{ + IrInstSrcSwitchBr *instruction = ir_build_instruction(irb, scope, source_node); + instruction->base.is_noreturn = true; + instruction->target_value = target_value; + instruction->else_block = else_block; + instruction->case_count = case_count; + instruction->cases = cases; + instruction->is_comptime = is_comptime; + instruction->switch_prongs_void = switch_prongs_void; + + ir_ref_instruction(target_value, irb->current_basic_block); + ir_ref_instruction(is_comptime, irb->current_basic_block); + ir_ref_bb(else_block); + ir_ref_instruction(switch_prongs_void, irb->current_basic_block); + + for (size_t i = 0; i < case_count; i += 1) { + ir_ref_instruction(cases[i].value, irb->current_basic_block); + ir_ref_bb(cases[i].block); + } + + return instruction; +} + +static IrInstSrc *ir_build_switch_target(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *target_value_ptr) +{ + IrInstSrcSwitchTarget *instruction = ir_build_instruction(irb, scope, source_node); + instruction->target_value_ptr = target_value_ptr; + + ir_ref_instruction(target_value_ptr, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_switch_var(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *target_value_ptr, IrInstSrc **prongs_ptr, size_t prongs_len) +{ + IrInstSrcSwitchVar *instruction = ir_build_instruction(irb, scope, source_node); + instruction->target_value_ptr = target_value_ptr; + instruction->prongs_ptr = prongs_ptr; + instruction->prongs_len = prongs_len; + + ir_ref_instruction(target_value_ptr, irb->current_basic_block); + for (size_t i = 0; i < prongs_len; i += 1) { + ir_ref_instruction(prongs_ptr[i], irb->current_basic_block); + } + + return &instruction->base; +} + +// For this instruction the switch_br must be set later. +static IrInstSrcSwitchElseVar *ir_build_switch_else_var(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *target_value_ptr) +{ + IrInstSrcSwitchElseVar *instruction = ir_build_instruction(irb, scope, source_node); + instruction->target_value_ptr = target_value_ptr; + + ir_ref_instruction(target_value_ptr, irb->current_basic_block); + + return instruction; +} + +static IrInstSrc *ir_build_import(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *name) { + IrInstSrcImport *instruction = ir_build_instruction(irb, scope, source_node); + instruction->name = name; + + ir_ref_instruction(name, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_ref_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *value) { + IrInstSrcRef *instruction = ir_build_instruction(irb, scope, source_node); + instruction->value = value; + + ir_ref_instruction(value, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_compile_err(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *msg) { + IrInstSrcCompileErr *instruction = ir_build_instruction(irb, scope, source_node); + instruction->msg = msg; + + ir_ref_instruction(msg, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_compile_log(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + size_t msg_count, IrInstSrc **msg_list) +{ + IrInstSrcCompileLog *instruction = ir_build_instruction(irb, scope, source_node); + instruction->msg_count = msg_count; + instruction->msg_list = msg_list; + + for (size_t i = 0; i < msg_count; i += 1) { + ir_ref_instruction(msg_list[i], irb->current_basic_block); + } + + return &instruction->base; +} + +static IrInstSrc *ir_build_err_name(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *value) { + IrInstSrcErrName *instruction = ir_build_instruction(irb, scope, source_node); + instruction->value = value; + + ir_ref_instruction(value, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_c_import(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { + IrInstSrcCImport *instruction = ir_build_instruction(irb, scope, source_node); + return &instruction->base; +} + +static IrInstSrc *ir_build_c_include(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *name) { + IrInstSrcCInclude *instruction = ir_build_instruction(irb, scope, source_node); + instruction->name = name; + + ir_ref_instruction(name, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_c_define(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *name, IrInstSrc *value) { + IrInstSrcCDefine *instruction = ir_build_instruction(irb, scope, source_node); + instruction->name = name; + instruction->value = value; + + ir_ref_instruction(name, irb->current_basic_block); + ir_ref_instruction(value, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_c_undef(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *name) { + IrInstSrcCUndef *instruction = ir_build_instruction(irb, scope, source_node); + instruction->name = name; + + ir_ref_instruction(name, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_embed_file(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *name) { + IrInstSrcEmbedFile *instruction = ir_build_instruction(irb, scope, source_node); + instruction->name = name; + + ir_ref_instruction(name, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_cmpxchg_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *type_value, IrInstSrc *ptr, IrInstSrc *cmp_value, IrInstSrc *new_value, + IrInstSrc *success_order_value, IrInstSrc *failure_order_value, bool is_weak, ResultLoc *result_loc) +{ + IrInstSrcCmpxchg *instruction = ir_build_instruction(irb, scope, source_node); + instruction->type_value = type_value; + instruction->ptr = ptr; + instruction->cmp_value = cmp_value; + instruction->new_value = new_value; + instruction->success_order_value = success_order_value; + instruction->failure_order_value = failure_order_value; + instruction->is_weak = is_weak; + instruction->result_loc = result_loc; + + ir_ref_instruction(type_value, irb->current_basic_block); + ir_ref_instruction(ptr, irb->current_basic_block); + ir_ref_instruction(cmp_value, irb->current_basic_block); + ir_ref_instruction(new_value, irb->current_basic_block); + ir_ref_instruction(success_order_value, irb->current_basic_block); + ir_ref_instruction(failure_order_value, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_fence(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *order) { + IrInstSrcFence *instruction = ir_build_instruction(irb, scope, source_node); + instruction->order = order; + + ir_ref_instruction(order, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_reduce(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *op, IrInstSrc *value) { + IrInstSrcReduce *instruction = ir_build_instruction(irb, scope, source_node); + instruction->op = op; + instruction->value = value; + + ir_ref_instruction(op, irb->current_basic_block); + ir_ref_instruction(value, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_truncate(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *dest_type, IrInstSrc *target) +{ + IrInstSrcTruncate *instruction = ir_build_instruction(irb, scope, source_node); + instruction->dest_type = dest_type; + instruction->target = target; + + ir_ref_instruction(dest_type, irb->current_basic_block); + ir_ref_instruction(target, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_int_cast(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *dest_type, + IrInstSrc *target) +{ + IrInstSrcIntCast *instruction = ir_build_instruction(irb, scope, source_node); + instruction->dest_type = dest_type; + instruction->target = target; + + ir_ref_instruction(dest_type, irb->current_basic_block); + ir_ref_instruction(target, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_float_cast(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *dest_type, + IrInstSrc *target) +{ + IrInstSrcFloatCast *instruction = ir_build_instruction(irb, scope, source_node); + instruction->dest_type = dest_type; + instruction->target = target; + + ir_ref_instruction(dest_type, irb->current_basic_block); + ir_ref_instruction(target, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_err_set_cast(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *dest_type, IrInstSrc *target) +{ + IrInstSrcErrSetCast *instruction = ir_build_instruction(irb, scope, source_node); + instruction->dest_type = dest_type; + instruction->target = target; + + ir_ref_instruction(dest_type, irb->current_basic_block); + ir_ref_instruction(target, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_int_to_float(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *dest_type, IrInstSrc *target) +{ + IrInstSrcIntToFloat *instruction = ir_build_instruction(irb, scope, source_node); + instruction->dest_type = dest_type; + instruction->target = target; + + ir_ref_instruction(dest_type, irb->current_basic_block); + ir_ref_instruction(target, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_float_to_int(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *dest_type, IrInstSrc *target) +{ + IrInstSrcFloatToInt *instruction = ir_build_instruction(irb, scope, source_node); + instruction->dest_type = dest_type; + instruction->target = target; + + ir_ref_instruction(dest_type, irb->current_basic_block); + ir_ref_instruction(target, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_bool_to_int(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *target) { + IrInstSrcBoolToInt *instruction = ir_build_instruction(irb, scope, source_node); + instruction->target = target; + + ir_ref_instruction(target, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_vector_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *len, + IrInstSrc *elem_type) +{ + IrInstSrcVectorType *instruction = ir_build_instruction(irb, scope, source_node); + instruction->len = len; + instruction->elem_type = elem_type; + + ir_ref_instruction(len, irb->current_basic_block); + ir_ref_instruction(elem_type, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_shuffle_vector(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *scalar_type, IrInstSrc *a, IrInstSrc *b, IrInstSrc *mask) +{ + IrInstSrcShuffleVector *instruction = ir_build_instruction(irb, scope, source_node); + instruction->scalar_type = scalar_type; + instruction->a = a; + instruction->b = b; + instruction->mask = mask; + + if (scalar_type != nullptr) ir_ref_instruction(scalar_type, irb->current_basic_block); + ir_ref_instruction(a, irb->current_basic_block); + ir_ref_instruction(b, irb->current_basic_block); + ir_ref_instruction(mask, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_splat_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *len, IrInstSrc *scalar) +{ + IrInstSrcSplat *instruction = ir_build_instruction(irb, scope, source_node); + instruction->len = len; + instruction->scalar = scalar; + + ir_ref_instruction(len, irb->current_basic_block); + ir_ref_instruction(scalar, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_bool_not(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *value) { + IrInstSrcBoolNot *instruction = ir_build_instruction(irb, scope, source_node); + instruction->value = value; + + ir_ref_instruction(value, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_memset_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *dest_ptr, IrInstSrc *byte, IrInstSrc *count) +{ + IrInstSrcMemset *instruction = ir_build_instruction(irb, scope, source_node); + instruction->dest_ptr = dest_ptr; + instruction->byte = byte; + instruction->count = count; + + ir_ref_instruction(dest_ptr, irb->current_basic_block); + ir_ref_instruction(byte, irb->current_basic_block); + ir_ref_instruction(count, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_memcpy_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *dest_ptr, IrInstSrc *src_ptr, IrInstSrc *count) +{ + IrInstSrcMemcpy *instruction = ir_build_instruction(irb, scope, source_node); + instruction->dest_ptr = dest_ptr; + instruction->src_ptr = src_ptr; + instruction->count = count; + + ir_ref_instruction(dest_ptr, irb->current_basic_block); + ir_ref_instruction(src_ptr, irb->current_basic_block); + ir_ref_instruction(count, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_slice_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *ptr, IrInstSrc *start, IrInstSrc *end, IrInstSrc *sentinel, + bool safety_check_on, ResultLoc *result_loc) +{ + IrInstSrcSlice *instruction = ir_build_instruction(irb, scope, source_node); + instruction->ptr = ptr; + instruction->start = start; + instruction->end = end; + instruction->sentinel = sentinel; + instruction->safety_check_on = safety_check_on; + instruction->result_loc = result_loc; + + ir_ref_instruction(ptr, irb->current_basic_block); + ir_ref_instruction(start, irb->current_basic_block); + if (end) ir_ref_instruction(end, irb->current_basic_block); + if (sentinel) ir_ref_instruction(sentinel, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_breakpoint(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { + IrInstSrcBreakpoint *instruction = ir_build_instruction(irb, scope, source_node); + return &instruction->base; +} + +static IrInstSrc *ir_build_return_address_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { + IrInstSrcReturnAddress *instruction = ir_build_instruction(irb, scope, source_node); + return &instruction->base; +} + +static IrInstSrc *ir_build_frame_address_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { + IrInstSrcFrameAddress *inst = ir_build_instruction(irb, scope, source_node); + return &inst->base; +} + +static IrInstSrc *ir_build_handle_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { + IrInstSrcFrameHandle *inst = ir_build_instruction(irb, scope, source_node); + return &inst->base; +} + +static IrInstSrc *ir_build_frame_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *fn) { + IrInstSrcFrameType *inst = ir_build_instruction(irb, scope, source_node); + inst->fn = fn; + + ir_ref_instruction(fn, irb->current_basic_block); + + return &inst->base; +} + +static IrInstSrc *ir_build_frame_size_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *fn) { + IrInstSrcFrameSize *inst = ir_build_instruction(irb, scope, source_node); + inst->fn = fn; + + ir_ref_instruction(fn, irb->current_basic_block); + + return &inst->base; +} + +static IrInstSrc *ir_build_overflow_op_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrOverflowOp op, IrInstSrc *type_value, IrInstSrc *op1, IrInstSrc *op2, IrInstSrc *result_ptr) +{ + IrInstSrcOverflowOp *instruction = ir_build_instruction(irb, scope, source_node); + instruction->op = op; + instruction->type_value = type_value; + instruction->op1 = op1; + instruction->op2 = op2; + instruction->result_ptr = result_ptr; + + ir_ref_instruction(type_value, irb->current_basic_block); + ir_ref_instruction(op1, irb->current_basic_block); + ir_ref_instruction(op2, irb->current_basic_block); + ir_ref_instruction(result_ptr, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_float_op_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *operand, + BuiltinFnId fn_id) +{ + IrInstSrcFloatOp *instruction = ir_build_instruction(irb, scope, source_node); + instruction->operand = operand; + instruction->fn_id = fn_id; + + ir_ref_instruction(operand, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_mul_add_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *type_value, IrInstSrc *op1, IrInstSrc *op2, IrInstSrc *op3) +{ + IrInstSrcMulAdd *instruction = ir_build_instruction(irb, scope, source_node); + instruction->type_value = type_value; + instruction->op1 = op1; + instruction->op2 = op2; + instruction->op3 = op3; + + ir_ref_instruction(type_value, irb->current_basic_block); + ir_ref_instruction(op1, irb->current_basic_block); + ir_ref_instruction(op2, irb->current_basic_block); + ir_ref_instruction(op3, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_align_of(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *type_value) { + IrInstSrcAlignOf *instruction = ir_build_instruction(irb, scope, source_node); + instruction->type_value = type_value; + + ir_ref_instruction(type_value, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_test_err_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *base_ptr, bool resolve_err_set, bool base_ptr_is_payload) +{ + IrInstSrcTestErr *instruction = ir_build_instruction(irb, scope, source_node); + instruction->base_ptr = base_ptr; + instruction->resolve_err_set = resolve_err_set; + instruction->base_ptr_is_payload = base_ptr_is_payload; + + ir_ref_instruction(base_ptr, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_unwrap_err_code_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *err_union_ptr) +{ + IrInstSrcUnwrapErrCode *inst = ir_build_instruction(irb, scope, source_node); + inst->err_union_ptr = err_union_ptr; + + ir_ref_instruction(err_union_ptr, irb->current_basic_block); + + return &inst->base; +} + +static IrInstSrc *ir_build_unwrap_err_payload_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *value, bool safety_check_on, bool initializing) +{ + IrInstSrcUnwrapErrPayload *inst = ir_build_instruction(irb, scope, source_node); + inst->value = value; + inst->safety_check_on = safety_check_on; + inst->initializing = initializing; + + ir_ref_instruction(value, irb->current_basic_block); + + return &inst->base; +} + +static IrInstSrc *ir_build_fn_proto(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc **param_types, IrInstSrc *align_value, IrInstSrc *callconv_value, + IrInstSrc *return_type, bool is_var_args) +{ + IrInstSrcFnProto *instruction = ir_build_instruction(irb, scope, source_node); + instruction->param_types = param_types; + instruction->align_value = align_value; + instruction->callconv_value = callconv_value; + instruction->return_type = return_type; + instruction->is_var_args = is_var_args; + + assert(source_node->type == NodeTypeFnProto); + size_t param_count = source_node->data.fn_proto.params.length; + if (is_var_args) param_count -= 1; + for (size_t i = 0; i < param_count; i += 1) { + if (param_types[i] != nullptr) ir_ref_instruction(param_types[i], irb->current_basic_block); + } + if (align_value != nullptr) ir_ref_instruction(align_value, irb->current_basic_block); + if (callconv_value != nullptr) ir_ref_instruction(callconv_value, irb->current_basic_block); + ir_ref_instruction(return_type, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_test_comptime(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *value) { + IrInstSrcTestComptime *instruction = ir_build_instruction(irb, scope, source_node); + instruction->value = value; + + ir_ref_instruction(value, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_ptr_cast_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *dest_type, IrInstSrc *ptr, bool safety_check_on) +{ + IrInstSrcPtrCast *instruction = ir_build_instruction( + irb, scope, source_node); + instruction->dest_type = dest_type; + instruction->ptr = ptr; + instruction->safety_check_on = safety_check_on; + + ir_ref_instruction(dest_type, irb->current_basic_block); + ir_ref_instruction(ptr, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_implicit_cast(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *operand, ResultLocCast *result_loc_cast) +{ + IrInstSrcImplicitCast *instruction = ir_build_instruction(irb, scope, source_node); + instruction->operand = operand; + instruction->result_loc_cast = result_loc_cast; + + ir_ref_instruction(operand, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_bit_cast_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *operand, ResultLocBitCast *result_loc_bit_cast) +{ + IrInstSrcBitCast *instruction = ir_build_instruction(irb, scope, source_node); + instruction->operand = operand; + instruction->result_loc_bit_cast = result_loc_bit_cast; + + ir_ref_instruction(operand, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_int_to_ptr_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *dest_type, IrInstSrc *target) +{ + IrInstSrcIntToPtr *instruction = ir_build_instruction(irb, scope, source_node); + instruction->dest_type = dest_type; + instruction->target = target; + + ir_ref_instruction(dest_type, irb->current_basic_block); + ir_ref_instruction(target, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_ptr_to_int_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *target) +{ + IrInstSrcPtrToInt *inst = ir_build_instruction(irb, scope, source_node); + inst->target = target; + + ir_ref_instruction(target, irb->current_basic_block); + + return &inst->base; +} + +static IrInstSrc *ir_build_int_to_enum_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *dest_type, IrInstSrc *target) +{ + IrInstSrcIntToEnum *instruction = ir_build_instruction(irb, scope, source_node); + instruction->dest_type = dest_type; + instruction->target = target; + + if (dest_type) ir_ref_instruction(dest_type, irb->current_basic_block); + ir_ref_instruction(target, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_enum_to_int(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *target) +{ + IrInstSrcEnumToInt *instruction = ir_build_instruction( + irb, scope, source_node); + instruction->target = target; + + ir_ref_instruction(target, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_int_to_err_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *target) +{ + IrInstSrcIntToErr *instruction = ir_build_instruction(irb, scope, source_node); + instruction->target = target; + + ir_ref_instruction(target, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_err_to_int_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *target) +{ + IrInstSrcErrToInt *instruction = ir_build_instruction( + irb, scope, source_node); + instruction->target = target; + + ir_ref_instruction(target, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_check_switch_prongs(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *target_value, IrInstSrcCheckSwitchProngsRange *ranges, size_t range_count, + AstNode* else_prong, bool have_underscore_prong) +{ + IrInstSrcCheckSwitchProngs *instruction = heap::c_allocator.create(); + instruction->base.id = have_underscore_prong ? + IrInstSrcIdCheckSwitchProngsUnderYes : IrInstSrcIdCheckSwitchProngsUnderNo; + instruction->base.base.scope = scope; + instruction->base.base.source_node = source_node; + instruction->base.base.debug_id = exec_next_debug_id(irb->exec); + instruction->base.owner_bb = irb->current_basic_block; + ir_instruction_append(irb->current_basic_block, &instruction->base); + + instruction->target_value = target_value; + instruction->ranges = ranges; + instruction->range_count = range_count; + instruction->else_prong = else_prong; + + ir_ref_instruction(target_value, irb->current_basic_block); + for (size_t i = 0; i < range_count; i += 1) { + ir_ref_instruction(ranges[i].start, irb->current_basic_block); + ir_ref_instruction(ranges[i].end, irb->current_basic_block); + } + + return &instruction->base; +} + +static IrInstSrc *ir_build_check_statement_is_void(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc* statement_value) +{ + IrInstSrcCheckStatementIsVoid *instruction = ir_build_instruction( + irb, scope, source_node); + instruction->statement_value = statement_value; + + ir_ref_instruction(statement_value, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_type_name(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *type_value) +{ + IrInstSrcTypeName *instruction = ir_build_instruction(irb, scope, source_node); + instruction->type_value = type_value; + + ir_ref_instruction(type_value, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_decl_ref(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, Tld *tld, LVal lval) { + IrInstSrcDeclRef *instruction = ir_build_instruction(irb, scope, source_node); + instruction->tld = tld; + instruction->lval = lval; + + return &instruction->base; +} + +static IrInstSrc *ir_build_panic_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *msg) { + IrInstSrcPanic *instruction = ir_build_instruction(irb, scope, source_node); + instruction->base.is_noreturn = true; + instruction->msg = msg; + + ir_ref_instruction(msg, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_tag_name_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *target) { + IrInstSrcTagName *instruction = ir_build_instruction(irb, scope, source_node); + instruction->target = target; + + ir_ref_instruction(target, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_field_parent_ptr_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *type_value, IrInstSrc *field_name, IrInstSrc *field_ptr) +{ + IrInstSrcFieldParentPtr *inst = ir_build_instruction( + irb, scope, source_node); + inst->type_value = type_value; + inst->field_name = field_name; + inst->field_ptr = field_ptr; + + ir_ref_instruction(type_value, irb->current_basic_block); + ir_ref_instruction(field_name, irb->current_basic_block); + ir_ref_instruction(field_ptr, irb->current_basic_block); + + return &inst->base; +} + +static IrInstSrc *ir_build_byte_offset_of(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *type_value, IrInstSrc *field_name) +{ + IrInstSrcByteOffsetOf *instruction = ir_build_instruction(irb, scope, source_node); + instruction->type_value = type_value; + instruction->field_name = field_name; + + ir_ref_instruction(type_value, irb->current_basic_block); + ir_ref_instruction(field_name, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_bit_offset_of(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *type_value, IrInstSrc *field_name) +{ + IrInstSrcBitOffsetOf *instruction = ir_build_instruction(irb, scope, source_node); + instruction->type_value = type_value; + instruction->field_name = field_name; + + ir_ref_instruction(type_value, irb->current_basic_block); + ir_ref_instruction(field_name, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_type_info(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *type_value) { + IrInstSrcTypeInfo *instruction = ir_build_instruction(irb, scope, source_node); + instruction->type_value = type_value; + + ir_ref_instruction(type_value, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *type_info) { + IrInstSrcType *instruction = ir_build_instruction(irb, scope, source_node); + instruction->type_info = type_info; + + ir_ref_instruction(type_info, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_set_eval_branch_quota(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *new_quota) +{ + IrInstSrcSetEvalBranchQuota *instruction = ir_build_instruction(irb, scope, source_node); + instruction->new_quota = new_quota; + + ir_ref_instruction(new_quota, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_align_cast_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *align_bytes, IrInstSrc *target) +{ + IrInstSrcAlignCast *instruction = ir_build_instruction(irb, scope, source_node); + instruction->align_bytes = align_bytes; + instruction->target = target; + + ir_ref_instruction(align_bytes, irb->current_basic_block); + ir_ref_instruction(target, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_resolve_result(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + ResultLoc *result_loc, IrInstSrc *ty) +{ + IrInstSrcResolveResult *instruction = ir_build_instruction(irb, scope, source_node); + instruction->result_loc = result_loc; + instruction->ty = ty; + + if (ty != nullptr) ir_ref_instruction(ty, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_reset_result(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + ResultLoc *result_loc) +{ + IrInstSrcResetResult *instruction = ir_build_instruction(irb, scope, source_node); + instruction->result_loc = result_loc; + instruction->base.is_gen = true; + + return &instruction->base; +} + +static IrInstSrc *ir_build_set_align_stack(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *align_bytes) +{ + IrInstSrcSetAlignStack *instruction = ir_build_instruction(irb, scope, source_node); + instruction->align_bytes = align_bytes; + + ir_ref_instruction(align_bytes, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_arg_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *fn_type, IrInstSrc *arg_index, bool allow_var) +{ + IrInstSrcArgType *instruction = heap::c_allocator.create(); + instruction->base.id = allow_var ? + IrInstSrcIdArgTypeAllowVarTrue : IrInstSrcIdArgTypeAllowVarFalse; + instruction->base.base.scope = scope; + instruction->base.base.source_node = source_node; + instruction->base.base.debug_id = exec_next_debug_id(irb->exec); + instruction->base.owner_bb = irb->current_basic_block; + ir_instruction_append(irb->current_basic_block, &instruction->base); + + instruction->fn_type = fn_type; + instruction->arg_index = arg_index; + + ir_ref_instruction(fn_type, irb->current_basic_block); + ir_ref_instruction(arg_index, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_error_return_trace_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstErrorReturnTraceOptional optional) +{ + IrInstSrcErrorReturnTrace *inst = ir_build_instruction(irb, scope, source_node); + inst->optional = optional; + + return &inst->base; +} + +static IrInstSrc *ir_build_error_union(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *err_set, IrInstSrc *payload) +{ + IrInstSrcErrorUnion *instruction = ir_build_instruction(irb, scope, source_node); + instruction->err_set = err_set; + instruction->payload = payload; + + ir_ref_instruction(err_set, irb->current_basic_block); + ir_ref_instruction(payload, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_atomic_rmw_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *operand_type, IrInstSrc *ptr, IrInstSrc *op, IrInstSrc *operand, + IrInstSrc *ordering) +{ + IrInstSrcAtomicRmw *instruction = ir_build_instruction(irb, scope, source_node); + instruction->operand_type = operand_type; + instruction->ptr = ptr; + instruction->op = op; + instruction->operand = operand; + instruction->ordering = ordering; + + ir_ref_instruction(operand_type, irb->current_basic_block); + ir_ref_instruction(ptr, irb->current_basic_block); + ir_ref_instruction(op, irb->current_basic_block); + ir_ref_instruction(operand, irb->current_basic_block); + ir_ref_instruction(ordering, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_atomic_load_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *operand_type, IrInstSrc *ptr, IrInstSrc *ordering) +{ + IrInstSrcAtomicLoad *instruction = ir_build_instruction(irb, scope, source_node); + instruction->operand_type = operand_type; + instruction->ptr = ptr; + instruction->ordering = ordering; + + ir_ref_instruction(operand_type, irb->current_basic_block); + ir_ref_instruction(ptr, irb->current_basic_block); + ir_ref_instruction(ordering, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_atomic_store_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *operand_type, IrInstSrc *ptr, IrInstSrc *value, IrInstSrc *ordering) +{ + IrInstSrcAtomicStore *instruction = ir_build_instruction(irb, scope, source_node); + instruction->operand_type = operand_type; + instruction->ptr = ptr; + instruction->value = value; + instruction->ordering = ordering; + + ir_ref_instruction(operand_type, irb->current_basic_block); + ir_ref_instruction(ptr, irb->current_basic_block); + ir_ref_instruction(value, irb->current_basic_block); + ir_ref_instruction(ordering, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_save_err_ret_addr_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { + IrInstSrcSaveErrRetAddr *inst = ir_build_instruction(irb, scope, source_node); + return &inst->base; +} + +static IrInstSrc *ir_build_add_implicit_return_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *value, ResultLocReturn *result_loc_ret) +{ + IrInstSrcAddImplicitReturnType *inst = ir_build_instruction(irb, scope, source_node); + inst->value = value; + inst->result_loc_ret = result_loc_ret; + + ir_ref_instruction(value, irb->current_basic_block); + + return &inst->base; +} + +static IrInstSrc *ir_build_has_decl(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *container, IrInstSrc *name) +{ + IrInstSrcHasDecl *instruction = ir_build_instruction(irb, scope, source_node); + instruction->container = container; + instruction->name = name; + + ir_ref_instruction(container, irb->current_basic_block); + ir_ref_instruction(name, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_undeclared_identifier(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, Buf *name) { + IrInstSrcUndeclaredIdent *instruction = ir_build_instruction(irb, scope, source_node); + instruction->name = name; + + return &instruction->base; +} + +static IrInstSrc *ir_build_check_runtime_scope(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *scope_is_comptime, IrInstSrc *is_comptime) { + IrInstSrcCheckRuntimeScope *instruction = ir_build_instruction(irb, scope, source_node); + instruction->scope_is_comptime = scope_is_comptime; + instruction->is_comptime = is_comptime; + + ir_ref_instruction(scope_is_comptime, irb->current_basic_block); + ir_ref_instruction(is_comptime, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_union_init_named_field(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *union_type, IrInstSrc *field_name, IrInstSrc *field_result_loc, IrInstSrc *result_loc) +{ + IrInstSrcUnionInitNamedField *instruction = ir_build_instruction(irb, scope, source_node); + instruction->union_type = union_type; + instruction->field_name = field_name; + instruction->field_result_loc = field_result_loc; + instruction->result_loc = result_loc; + + ir_ref_instruction(union_type, irb->current_basic_block); + ir_ref_instruction(field_name, irb->current_basic_block); + ir_ref_instruction(field_result_loc, irb->current_basic_block); + if (result_loc != nullptr) ir_ref_instruction(result_loc, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_alloca_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *align, const char *name_hint, IrInstSrc *is_comptime) +{ + IrInstSrcAlloca *instruction = ir_build_instruction(irb, scope, source_node); + instruction->base.is_gen = true; + instruction->align = align; + instruction->name_hint = name_hint; + instruction->is_comptime = is_comptime; + + if (align != nullptr) ir_ref_instruction(align, irb->current_basic_block); + if (is_comptime != nullptr) ir_ref_instruction(is_comptime, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_end_expr(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *value, ResultLoc *result_loc) +{ + IrInstSrcEndExpr *instruction = ir_build_instruction(irb, scope, source_node); + instruction->base.is_gen = true; + instruction->value = value; + instruction->result_loc = result_loc; + + ir_ref_instruction(value, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrcSuspendBegin *ir_build_suspend_begin_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { + return ir_build_instruction(irb, scope, source_node); +} + +static IrInstSrc *ir_build_suspend_finish_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrcSuspendBegin *begin) +{ + IrInstSrcSuspendFinish *inst = ir_build_instruction(irb, scope, source_node); + inst->begin = begin; + + ir_ref_instruction(&begin->base, irb->current_basic_block); + + return &inst->base; +} + +static IrInstSrc *ir_build_await_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *frame, ResultLoc *result_loc, bool is_nosuspend) +{ + IrInstSrcAwait *instruction = ir_build_instruction(irb, scope, source_node); + instruction->frame = frame; + instruction->result_loc = result_loc; + instruction->is_nosuspend = is_nosuspend; + + ir_ref_instruction(frame, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_resume_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *frame) { + IrInstSrcResume *instruction = ir_build_instruction(irb, scope, source_node); + instruction->frame = frame; + + ir_ref_instruction(frame, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrcSpillBegin *ir_build_spill_begin_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *operand, SpillId spill_id) +{ + IrInstSrcSpillBegin *instruction = ir_build_instruction(irb, scope, source_node); + instruction->operand = operand; + instruction->spill_id = spill_id; + + ir_ref_instruction(operand, irb->current_basic_block); + + return instruction; +} + +static IrInstSrc *ir_build_spill_end_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrcSpillBegin *begin) +{ + IrInstSrcSpillEnd *instruction = ir_build_instruction(irb, scope, source_node); + instruction->begin = begin; + + ir_ref_instruction(&begin->base, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_wasm_memory_size_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *index) { + IrInstSrcWasmMemorySize *instruction = ir_build_instruction(irb, scope, source_node); + instruction->index = index; + + ir_ref_instruction(index, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_wasm_memory_grow_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *index, IrInstSrc *delta) { + IrInstSrcWasmMemoryGrow *instruction = ir_build_instruction(irb, scope, source_node); + instruction->index = index; + instruction->delta = delta; + + ir_ref_instruction(index, irb->current_basic_block); + ir_ref_instruction(delta, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { + IrInstSrcSrc *instruction = ir_build_instruction(irb, scope, source_node); + + return &instruction->base; +} + +static void ir_count_defers(IrBuilderSrc *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { + results[ReturnKindUnconditional] = 0; + results[ReturnKindError] = 0; + + Scope *scope = inner_scope; + + while (scope != outer_scope) { + assert(scope); + switch (scope->id) { + case ScopeIdDefer: { + AstNode *defer_node = scope->source_node; + assert(defer_node->type == NodeTypeDefer); + ReturnKind defer_kind = defer_node->data.defer.kind; + results[defer_kind] += 1; + scope = scope->parent; + continue; + } + case ScopeIdDecls: + case ScopeIdFnDef: + return; + case ScopeIdBlock: + case ScopeIdVarDecl: + case ScopeIdLoop: + case ScopeIdSuspend: + case ScopeIdCompTime: + case ScopeIdNoSuspend: + case ScopeIdRuntime: + case ScopeIdTypeOf: + case ScopeIdExpr: + scope = scope->parent; + continue; + case ScopeIdDeferExpr: + case ScopeIdCImport: + zig_unreachable(); + } + } +} + +static IrInstSrc *ir_mark_gen(IrInstSrc *instruction) { + instruction->is_gen = true; + return instruction; +} + +static bool ir_gen_defers_for_block(IrBuilderSrc *irb, Scope *inner_scope, Scope *outer_scope, bool *is_noreturn, IrInstSrc *err_value) { + Scope *scope = inner_scope; + if (is_noreturn != nullptr) *is_noreturn = false; + while (scope != outer_scope) { + if (!scope) + return true; + + switch (scope->id) { + case ScopeIdDefer: { + AstNode *defer_node = scope->source_node; + assert(defer_node->type == NodeTypeDefer); + ReturnKind defer_kind = defer_node->data.defer.kind; + AstNode *defer_expr_node = defer_node->data.defer.expr; + AstNode *defer_var_node = defer_node->data.defer.err_payload; + + if (defer_kind == ReturnKindError && err_value == nullptr) { + // This is an `errdefer` but we're generating code for a + // `return` that doesn't return an error, skip it + scope = scope->parent; + continue; + } + + Scope *defer_expr_scope = defer_node->data.defer.expr_scope; + if (defer_var_node != nullptr) { + assert(defer_kind == ReturnKindError); + assert(defer_var_node->type == NodeTypeIdentifier); + Buf *var_name = node_identifier_buf(defer_var_node); + + if (defer_expr_node->type == NodeTypeUnreachable) { + add_node_error(irb->codegen, defer_var_node, + buf_sprintf("unused variable: '%s'", buf_ptr(var_name))); + return false; + } + + IrInstSrc *is_comptime; + if (ir_should_inline(irb->exec, defer_expr_scope)) { + is_comptime = ir_build_const_bool(irb, defer_expr_scope, + defer_expr_node, true); + } else { + is_comptime = ir_build_test_comptime(irb, defer_expr_scope, + defer_expr_node, err_value); + } + + ZigVar *err_var = ir_create_var(irb, defer_var_node, defer_expr_scope, + var_name, true, true, false, is_comptime); + build_decl_var_and_init(irb, defer_expr_scope, defer_var_node, err_var, err_value, + buf_ptr(var_name), is_comptime); + + defer_expr_scope = err_var->child_scope; + } + + IrInstSrc *defer_expr_value = ir_gen_node(irb, defer_expr_node, defer_expr_scope); + if (defer_expr_value == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + + if (defer_expr_value->is_noreturn) { + if (is_noreturn != nullptr) *is_noreturn = true; + } else { + ir_mark_gen(ir_build_check_statement_is_void(irb, defer_expr_scope, defer_expr_node, + defer_expr_value)); + } + scope = scope->parent; + continue; + } + case ScopeIdDecls: + case ScopeIdFnDef: + return true; + case ScopeIdBlock: + case ScopeIdVarDecl: + case ScopeIdLoop: + case ScopeIdSuspend: + case ScopeIdCompTime: + case ScopeIdNoSuspend: + case ScopeIdRuntime: + case ScopeIdTypeOf: + case ScopeIdExpr: + scope = scope->parent; + continue; + case ScopeIdDeferExpr: + case ScopeIdCImport: + zig_unreachable(); + } + } + return true; +} + +static void ir_set_cursor_at_end(IrBuilderSrc *irb, IrBasicBlockSrc *basic_block) { + assert(basic_block); + irb->current_basic_block = basic_block; +} + +static void ir_set_cursor_at_end_and_append_block(IrBuilderSrc *irb, IrBasicBlockSrc *basic_block) { + basic_block->index = irb->exec->basic_block_list.length; + irb->exec->basic_block_list.append(basic_block); + ir_set_cursor_at_end(irb, basic_block); +} + +static ScopeSuspend *get_scope_suspend(Scope *scope) { + while (scope) { + if (scope->id == ScopeIdSuspend) + return (ScopeSuspend *)scope; + if (scope->id == ScopeIdFnDef) + return nullptr; + + scope = scope->parent; + } + return nullptr; +} + +static ScopeDeferExpr *get_scope_defer_expr(Scope *scope) { + while (scope) { + if (scope->id == ScopeIdDeferExpr) + return (ScopeDeferExpr *)scope; + if (scope->id == ScopeIdFnDef) + return nullptr; + + scope = scope->parent; + } + return nullptr; +} + +static IrInstSrc *ir_gen_return(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { + assert(node->type == NodeTypeReturnExpr); + + ScopeDeferExpr *scope_defer_expr = get_scope_defer_expr(scope); + if (scope_defer_expr) { + if (!scope_defer_expr->reported_err) { + add_node_error(irb->codegen, node, buf_sprintf("cannot return from defer expression")); + scope_defer_expr->reported_err = true; + } + return irb->codegen->invalid_inst_src; + } + + Scope *outer_scope = irb->exec->begin_scope; + + AstNode *expr_node = node->data.return_expr.expr; + switch (node->data.return_expr.kind) { + case ReturnKindUnconditional: + { + ResultLocReturn *result_loc_ret = heap::c_allocator.create(); + result_loc_ret->base.id = ResultLocIdReturn; + ir_build_reset_result(irb, scope, node, &result_loc_ret->base); + + IrInstSrc *return_value; + if (expr_node) { + // Temporarily set this so that if we return a type it gets the name of the function + ZigFn *prev_name_fn = irb->exec->name_fn; + irb->exec->name_fn = exec_fn_entry(irb->exec); + return_value = ir_gen_node_extra(irb, expr_node, scope, LValNone, &result_loc_ret->base); + irb->exec->name_fn = prev_name_fn; + if (return_value == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + } else { + return_value = ir_build_const_void(irb, scope, node); + ir_build_end_expr(irb, scope, node, return_value, &result_loc_ret->base); + } + + ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, node, return_value, result_loc_ret)); + + size_t defer_counts[2]; + ir_count_defers(irb, scope, outer_scope, defer_counts); + bool have_err_defers = defer_counts[ReturnKindError] > 0; + if (!have_err_defers && !irb->codegen->have_err_ret_tracing) { + // only generate unconditional defers + if (!ir_gen_defers_for_block(irb, scope, outer_scope, nullptr, nullptr)) + return irb->codegen->invalid_inst_src; + IrInstSrc *result = ir_build_return_src(irb, scope, node, nullptr); + result_loc_ret->base.source_instruction = result; + return result; + } + bool should_inline = ir_should_inline(irb->exec, scope); + + IrBasicBlockSrc *err_block = ir_create_basic_block(irb, scope, "ErrRetErr"); + IrBasicBlockSrc *ok_block = ir_create_basic_block(irb, scope, "ErrRetOk"); + + IrInstSrc *is_err = ir_build_test_err_src(irb, scope, node, return_value, false, true); + + IrInstSrc *is_comptime; + if (should_inline) { + is_comptime = ir_build_const_bool(irb, scope, node, should_inline); + } else { + is_comptime = ir_build_test_comptime(irb, scope, node, is_err); + } + + ir_mark_gen(ir_build_cond_br(irb, scope, node, is_err, err_block, ok_block, is_comptime)); + IrBasicBlockSrc *ret_stmt_block = ir_create_basic_block(irb, scope, "RetStmt"); + + ir_set_cursor_at_end_and_append_block(irb, err_block); + if (!ir_gen_defers_for_block(irb, scope, outer_scope, nullptr, return_value)) + return irb->codegen->invalid_inst_src; + if (irb->codegen->have_err_ret_tracing && !should_inline) { + ir_build_save_err_ret_addr_src(irb, scope, node); + } + ir_build_br(irb, scope, node, ret_stmt_block, is_comptime); + + ir_set_cursor_at_end_and_append_block(irb, ok_block); + if (!ir_gen_defers_for_block(irb, scope, outer_scope, nullptr, nullptr)) + return irb->codegen->invalid_inst_src; + ir_build_br(irb, scope, node, ret_stmt_block, is_comptime); + + ir_set_cursor_at_end_and_append_block(irb, ret_stmt_block); + IrInstSrc *result = ir_build_return_src(irb, scope, node, nullptr); + result_loc_ret->base.source_instruction = result; + return result; + } + case ReturnKindError: + { + assert(expr_node); + IrInstSrc *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr); + if (err_union_ptr == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + IrInstSrc *is_err_val = ir_build_test_err_src(irb, scope, node, err_union_ptr, true, false); + + IrBasicBlockSrc *return_block = ir_create_basic_block(irb, scope, "ErrRetReturn"); + IrBasicBlockSrc *continue_block = ir_create_basic_block(irb, scope, "ErrRetContinue"); + IrInstSrc *is_comptime; + bool should_inline = ir_should_inline(irb->exec, scope); + if (should_inline) { + is_comptime = ir_build_const_bool(irb, scope, node, true); + } else { + is_comptime = ir_build_test_comptime(irb, scope, node, is_err_val); + } + ir_mark_gen(ir_build_cond_br(irb, scope, node, is_err_val, return_block, continue_block, is_comptime)); + + ir_set_cursor_at_end_and_append_block(irb, return_block); + IrInstSrc *err_val_ptr = ir_build_unwrap_err_code_src(irb, scope, node, err_union_ptr); + IrInstSrc *err_val = ir_build_load_ptr(irb, scope, node, err_val_ptr); + ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, node, err_val, nullptr)); + IrInstSrcSpillBegin *spill_begin = ir_build_spill_begin_src(irb, scope, node, err_val, + SpillIdRetErrCode); + ResultLocReturn *result_loc_ret = heap::c_allocator.create(); + result_loc_ret->base.id = ResultLocIdReturn; + ir_build_reset_result(irb, scope, node, &result_loc_ret->base); + ir_build_end_expr(irb, scope, node, err_val, &result_loc_ret->base); + + bool is_noreturn = false; + if (!ir_gen_defers_for_block(irb, scope, outer_scope, &is_noreturn, err_val)) { + return irb->codegen->invalid_inst_src; + } + if (!is_noreturn) { + if (irb->codegen->have_err_ret_tracing && !should_inline) { + ir_build_save_err_ret_addr_src(irb, scope, node); + } + err_val = ir_build_spill_end_src(irb, scope, node, spill_begin); + IrInstSrc *ret_inst = ir_build_return_src(irb, scope, node, err_val); + result_loc_ret->base.source_instruction = ret_inst; + } + + ir_set_cursor_at_end_and_append_block(irb, continue_block); + IrInstSrc *unwrapped_ptr = ir_build_unwrap_err_payload_src(irb, scope, node, err_union_ptr, false, false); + if (lval == LValPtr) + return unwrapped_ptr; + else + return ir_expr_wrap(irb, scope, ir_build_load_ptr(irb, scope, node, unwrapped_ptr), result_loc); + } + } + zig_unreachable(); +} + +ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_scope, + Buf *name, bool src_is_const, bool gen_is_const, bool is_shadowable, IrInstSrc *is_comptime, + bool skip_name_check) +{ + ZigVar *variable_entry = heap::c_allocator.create(); + variable_entry->parent_scope = parent_scope; + variable_entry->shadowable = is_shadowable; + variable_entry->is_comptime = is_comptime; + variable_entry->src_arg_index = SIZE_MAX; + variable_entry->const_value = codegen->pass1_arena->create(); + + if (is_comptime != nullptr) { + is_comptime->base.ref_count += 1; + } + + if (name) { + variable_entry->name = strdup(buf_ptr(name)); + + if (!skip_name_check) { + ZigVar *existing_var = find_variable(codegen, parent_scope, name, nullptr); + if (existing_var && !existing_var->shadowable) { + if (existing_var->var_type == nullptr || !type_is_invalid(existing_var->var_type)) { + ErrorMsg *msg = add_node_error(codegen, node, + buf_sprintf("redeclaration of variable '%s'", buf_ptr(name))); + add_error_note(codegen, msg, existing_var->decl_node, buf_sprintf("previous declaration is here")); + } + variable_entry->var_type = codegen->builtin_types.entry_invalid; + } else { + ZigType *type; + if (get_primitive_type(codegen, name, &type) != ErrorPrimitiveTypeNotFound) { + add_node_error(codegen, node, + buf_sprintf("variable shadows primitive type '%s'", buf_ptr(name))); + variable_entry->var_type = codegen->builtin_types.entry_invalid; + } else { + Tld *tld = find_decl(codegen, parent_scope, name); + if (tld != nullptr) { + bool want_err_msg = true; + if (tld->id == TldIdVar) { + ZigVar *var = reinterpret_cast(tld)->var; + if (var != nullptr && var->var_type != nullptr && type_is_invalid(var->var_type)) { + want_err_msg = false; + } + } + if (want_err_msg) { + ErrorMsg *msg = add_node_error(codegen, node, + buf_sprintf("redefinition of '%s'", buf_ptr(name))); + add_error_note(codegen, msg, tld->source_node, buf_sprintf("previous definition is here")); + } + variable_entry->var_type = codegen->builtin_types.entry_invalid; + } + } + } + } + } else { + assert(is_shadowable); + // TODO make this name not actually be in scope. user should be able to make a variable called "_anon" + // might already be solved, let's just make sure it has test coverage + // maybe we put a prefix on this so the debug info doesn't clobber user debug info for same named variables + variable_entry->name = "_anon"; + } + + variable_entry->src_is_const = src_is_const; + variable_entry->gen_is_const = gen_is_const; + variable_entry->decl_node = node; + variable_entry->child_scope = create_var_scope(codegen, node, parent_scope, variable_entry); + + return variable_entry; +} + + +// Set name to nullptr to make the variable anonymous (not visible to programmer). +// After you call this function var->child_scope has the variable in scope +static ZigVar *ir_create_var(IrBuilderSrc *irb, AstNode *node, Scope *scope, Buf *name, + bool src_is_const, bool gen_is_const, bool is_shadowable, IrInstSrc *is_comptime) +{ + bool is_underscored = name ? buf_eql_str(name, "_") : false; + ZigVar *var = create_local_var(irb->codegen, node, scope, + (is_underscored ? nullptr : name), src_is_const, gen_is_const, + (is_underscored ? true : is_shadowable), is_comptime, false); + assert(var->child_scope); + return var; +} + +static ResultLocPeer *create_peer_result(ResultLocPeerParent *peer_parent) { + ResultLocPeer *result = heap::c_allocator.create(); + result->base.id = ResultLocIdPeer; + result->base.source_instruction = peer_parent->base.source_instruction; + result->parent = peer_parent; + result->base.allow_write_through_const = peer_parent->parent->allow_write_through_const; + return result; +} + +static bool is_duplicate_label(CodeGen *g, Scope *scope, AstNode *node, Buf *name) { + if (name == nullptr) return false; + + for (;;) { + if (scope == nullptr || scope->id == ScopeIdFnDef) { + break; + } else if (scope->id == ScopeIdBlock || scope->id == ScopeIdLoop) { + Buf *this_block_name = scope->id == ScopeIdBlock ? ((ScopeBlock *)scope)->name : ((ScopeLoop *)scope)->name; + if (this_block_name != nullptr && buf_eql_buf(name, this_block_name)) { + ErrorMsg *msg = add_node_error(g, node, buf_sprintf("redeclaration of label '%s'", buf_ptr(name))); + add_error_note(g, msg, scope->source_node, buf_sprintf("previous declaration is here")); + return true; + } + } + scope = scope->parent; + } + return false; +} + +static IrInstSrc *ir_gen_block(IrBuilderSrc *irb, Scope *parent_scope, AstNode *block_node, LVal lval, + ResultLoc *result_loc) +{ + assert(block_node->type == NodeTypeBlock); + + ZigList incoming_values = {0}; + ZigList incoming_blocks = {0}; + + if (is_duplicate_label(irb->codegen, parent_scope, block_node, block_node->data.block.name)) + return irb->codegen->invalid_inst_src; + + ScopeBlock *scope_block = create_block_scope(irb->codegen, block_node, parent_scope); + + Scope *outer_block_scope = &scope_block->base; + Scope *child_scope = outer_block_scope; + + ZigFn *fn_entry = scope_fn_entry(parent_scope); + if (fn_entry && fn_entry->child_scope == parent_scope) { + fn_entry->def_scope = scope_block; + } + + if (block_node->data.block.statements.length == 0) { + if (scope_block->name != nullptr) { + add_node_error(irb->codegen, block_node, buf_sprintf("unused block label")); + } + // {} + return ir_lval_wrap(irb, parent_scope, ir_build_const_void(irb, child_scope, block_node), lval, result_loc); + } + + if (block_node->data.block.name != nullptr) { + scope_block->lval = lval; + scope_block->incoming_blocks = &incoming_blocks; + scope_block->incoming_values = &incoming_values; + scope_block->end_block = ir_create_basic_block(irb, parent_scope, "BlockEnd"); + scope_block->is_comptime = ir_build_const_bool(irb, parent_scope, block_node, + ir_should_inline(irb->exec, parent_scope)); + + scope_block->peer_parent = heap::c_allocator.create(); + scope_block->peer_parent->base.id = ResultLocIdPeerParent; + scope_block->peer_parent->base.source_instruction = scope_block->is_comptime; + scope_block->peer_parent->base.allow_write_through_const = result_loc->allow_write_through_const; + scope_block->peer_parent->end_bb = scope_block->end_block; + scope_block->peer_parent->is_comptime = scope_block->is_comptime; + scope_block->peer_parent->parent = result_loc; + ir_build_reset_result(irb, parent_scope, block_node, &scope_block->peer_parent->base); + } + + bool is_continuation_unreachable = false; + bool found_invalid_inst = false; + IrInstSrc *noreturn_return_value = nullptr; + for (size_t i = 0; i < block_node->data.block.statements.length; i += 1) { + AstNode *statement_node = block_node->data.block.statements.at(i); + + IrInstSrc *statement_value = ir_gen_node(irb, statement_node, child_scope); + if (statement_value == irb->codegen->invalid_inst_src) { + // keep generating all the elements of the block in case of error, + // we want to collect other compile errors + found_invalid_inst = true; + continue; + } + + is_continuation_unreachable = instr_is_unreachable(statement_value); + if (is_continuation_unreachable) { + // keep the last noreturn statement value around in case we need to return it + noreturn_return_value = statement_value; + } + // This logic must be kept in sync with + // [STMT_EXPR_TEST_THING] <--- (search this token) + if (statement_node->type == NodeTypeDefer) { + // defer starts a new scope + child_scope = statement_node->data.defer.child_scope; + assert(child_scope); + } else if (statement_value->id == IrInstSrcIdDeclVar) { + // variable declarations start a new scope + IrInstSrcDeclVar *decl_var_instruction = (IrInstSrcDeclVar *)statement_value; + child_scope = decl_var_instruction->var->child_scope; + } else if (!is_continuation_unreachable) { + // this statement's value must be void + ir_mark_gen(ir_build_check_statement_is_void(irb, child_scope, statement_node, statement_value)); + } + } + + if (scope_block->name != nullptr && scope_block->name_used == false) { + add_node_error(irb->codegen, block_node, buf_sprintf("unused block label")); + } + + if (found_invalid_inst) + return irb->codegen->invalid_inst_src; + + if (is_continuation_unreachable) { + assert(noreturn_return_value != nullptr); + if (block_node->data.block.name == nullptr || incoming_blocks.length == 0) { + return noreturn_return_value; + } + + if (scope_block->peer_parent != nullptr && scope_block->peer_parent->peers.length != 0) { + scope_block->peer_parent->peers.last()->next_bb = scope_block->end_block; + } + ir_set_cursor_at_end_and_append_block(irb, scope_block->end_block); + IrInstSrc *phi = ir_build_phi(irb, parent_scope, block_node, incoming_blocks.length, + incoming_blocks.items, incoming_values.items, scope_block->peer_parent); + return ir_expr_wrap(irb, parent_scope, phi, result_loc); + } else { + incoming_blocks.append(irb->current_basic_block); + IrInstSrc *else_expr_result = ir_mark_gen(ir_build_const_void(irb, parent_scope, block_node)); + + if (scope_block->peer_parent != nullptr) { + ResultLocPeer *peer_result = create_peer_result(scope_block->peer_parent); + scope_block->peer_parent->peers.append(peer_result); + ir_build_end_expr(irb, parent_scope, block_node, else_expr_result, &peer_result->base); + + if (scope_block->peer_parent->peers.length != 0) { + scope_block->peer_parent->peers.last()->next_bb = scope_block->end_block; + } + } + + incoming_values.append(else_expr_result); + } + + bool is_return_from_fn = block_node == irb->main_block_node; + if (!is_return_from_fn) { + if (!ir_gen_defers_for_block(irb, child_scope, outer_block_scope, nullptr, nullptr)) + return irb->codegen->invalid_inst_src; + } + + IrInstSrc *result; + if (block_node->data.block.name != nullptr) { + ir_mark_gen(ir_build_br(irb, parent_scope, block_node, scope_block->end_block, scope_block->is_comptime)); + ir_set_cursor_at_end_and_append_block(irb, scope_block->end_block); + IrInstSrc *phi = ir_build_phi(irb, parent_scope, block_node, incoming_blocks.length, + incoming_blocks.items, incoming_values.items, scope_block->peer_parent); + result = ir_expr_wrap(irb, parent_scope, phi, result_loc); + } else { + IrInstSrc *void_inst = ir_mark_gen(ir_build_const_void(irb, child_scope, block_node)); + result = ir_lval_wrap(irb, parent_scope, void_inst, lval, result_loc); + } + if (!is_return_from_fn) + return result; + + // no need for save_err_ret_addr because this cannot return error + // only generate unconditional defers + + ir_mark_gen(ir_build_add_implicit_return_type(irb, child_scope, block_node, result, nullptr)); + ResultLocReturn *result_loc_ret = heap::c_allocator.create(); + result_loc_ret->base.id = ResultLocIdReturn; + ir_build_reset_result(irb, parent_scope, block_node, &result_loc_ret->base); + ir_mark_gen(ir_build_end_expr(irb, parent_scope, block_node, result, &result_loc_ret->base)); + if (!ir_gen_defers_for_block(irb, child_scope, outer_block_scope, nullptr, nullptr)) + return irb->codegen->invalid_inst_src; + return ir_mark_gen(ir_build_return_src(irb, child_scope, result->base.source_node, result)); +} + +static IrInstSrc *ir_gen_bin_op_id(IrBuilderSrc *irb, Scope *scope, AstNode *node, IrBinOp op_id) { + Scope *inner_scope = scope; + if (op_id == IrBinOpArrayCat || op_id == IrBinOpArrayMult) { + inner_scope = create_comptime_scope(irb->codegen, node, scope); + } + + IrInstSrc *op1 = ir_gen_node(irb, node->data.bin_op_expr.op1, inner_scope); + IrInstSrc *op2 = ir_gen_node(irb, node->data.bin_op_expr.op2, inner_scope); + + if (op1 == irb->codegen->invalid_inst_src || op2 == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + + return ir_build_bin_op(irb, scope, node, op_id, op1, op2, true); +} + +static IrInstSrc *ir_gen_merge_err_sets(IrBuilderSrc *irb, Scope *scope, AstNode *node) { + IrInstSrc *op1 = ir_gen_node(irb, node->data.bin_op_expr.op1, scope); + IrInstSrc *op2 = ir_gen_node(irb, node->data.bin_op_expr.op2, scope); + + if (op1 == irb->codegen->invalid_inst_src || op2 == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + + // TODO only pass type_name when the || operator is the top level AST node in the var decl expr + Buf bare_name = BUF_INIT; + Buf *type_name = get_anon_type_name(irb->codegen, irb->exec, "error", scope, node, &bare_name); + + return ir_build_merge_err_sets(irb, scope, node, op1, op2, type_name); +} + +static IrInstSrc *ir_gen_assign(IrBuilderSrc *irb, Scope *scope, AstNode *node) { + IrInstSrc *lvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op1, scope, LValAssign, nullptr); + if (lvalue == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + + ResultLocInstruction *result_loc_inst = heap::c_allocator.create(); + result_loc_inst->base.id = ResultLocIdInstruction; + result_loc_inst->base.source_instruction = lvalue; + ir_ref_instruction(lvalue, irb->current_basic_block); + ir_build_reset_result(irb, scope, node, &result_loc_inst->base); + + IrInstSrc *rvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op2, scope, LValNone, + &result_loc_inst->base); + if (rvalue == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + + return ir_build_const_void(irb, scope, node); +} + +static IrInstSrc *ir_gen_assign_op(IrBuilderSrc *irb, Scope *scope, AstNode *node, IrBinOp op_id) { + IrInstSrc *lvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op1, scope, LValAssign, nullptr); + if (lvalue == irb->codegen->invalid_inst_src) + return lvalue; + IrInstSrc *op1 = ir_build_load_ptr(irb, scope, node->data.bin_op_expr.op1, lvalue); + IrInstSrc *op2 = ir_gen_node(irb, node->data.bin_op_expr.op2, scope); + if (op2 == irb->codegen->invalid_inst_src) + return op2; + IrInstSrc *result = ir_build_bin_op(irb, scope, node, op_id, op1, op2, true); + ir_build_store_ptr(irb, scope, node, lvalue, result); + return ir_build_const_void(irb, scope, node); +} + +static IrInstSrc *ir_gen_bool_or(IrBuilderSrc *irb, Scope *scope, AstNode *node) { + assert(node->type == NodeTypeBinOpExpr); + + IrInstSrc *val1 = ir_gen_node(irb, node->data.bin_op_expr.op1, scope); + if (val1 == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + IrBasicBlockSrc *post_val1_block = irb->current_basic_block; + + IrInstSrc *is_comptime; + if (ir_should_inline(irb->exec, scope)) { + is_comptime = ir_build_const_bool(irb, scope, node, true); + } else { + is_comptime = ir_build_test_comptime(irb, scope, node, val1); + } + + // block for when val1 == false + IrBasicBlockSrc *false_block = ir_create_basic_block(irb, scope, "BoolOrFalse"); + // block for when val1 == true (don't even evaluate the second part) + IrBasicBlockSrc *true_block = ir_create_basic_block(irb, scope, "BoolOrTrue"); + + ir_build_cond_br(irb, scope, node, val1, true_block, false_block, is_comptime); + + ir_set_cursor_at_end_and_append_block(irb, false_block); + IrInstSrc *val2 = ir_gen_node(irb, node->data.bin_op_expr.op2, scope); + if (val2 == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + IrBasicBlockSrc *post_val2_block = irb->current_basic_block; + + ir_build_br(irb, scope, node, true_block, is_comptime); + + ir_set_cursor_at_end_and_append_block(irb, true_block); + + IrInstSrc **incoming_values = heap::c_allocator.allocate(2); + incoming_values[0] = val1; + incoming_values[1] = val2; + IrBasicBlockSrc **incoming_blocks = heap::c_allocator.allocate(2); + incoming_blocks[0] = post_val1_block; + incoming_blocks[1] = post_val2_block; + + return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, nullptr); +} + +static IrInstSrc *ir_gen_bool_and(IrBuilderSrc *irb, Scope *scope, AstNode *node) { + assert(node->type == NodeTypeBinOpExpr); + + IrInstSrc *val1 = ir_gen_node(irb, node->data.bin_op_expr.op1, scope); + if (val1 == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + IrBasicBlockSrc *post_val1_block = irb->current_basic_block; + + IrInstSrc *is_comptime; + if (ir_should_inline(irb->exec, scope)) { + is_comptime = ir_build_const_bool(irb, scope, node, true); + } else { + is_comptime = ir_build_test_comptime(irb, scope, node, val1); + } + + // block for when val1 == true + IrBasicBlockSrc *true_block = ir_create_basic_block(irb, scope, "BoolAndTrue"); + // block for when val1 == false (don't even evaluate the second part) + IrBasicBlockSrc *false_block = ir_create_basic_block(irb, scope, "BoolAndFalse"); + + ir_build_cond_br(irb, scope, node, val1, true_block, false_block, is_comptime); + + ir_set_cursor_at_end_and_append_block(irb, true_block); + IrInstSrc *val2 = ir_gen_node(irb, node->data.bin_op_expr.op2, scope); + if (val2 == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + IrBasicBlockSrc *post_val2_block = irb->current_basic_block; + + ir_build_br(irb, scope, node, false_block, is_comptime); + + ir_set_cursor_at_end_and_append_block(irb, false_block); + + IrInstSrc **incoming_values = heap::c_allocator.allocate(2); + incoming_values[0] = val1; + incoming_values[1] = val2; + IrBasicBlockSrc **incoming_blocks = heap::c_allocator.allocate(2); + incoming_blocks[0] = post_val1_block; + incoming_blocks[1] = post_val2_block; + + return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, nullptr); +} + +static ResultLocPeerParent *ir_build_result_peers(IrBuilderSrc *irb, IrInstSrc *cond_br_inst, + IrBasicBlockSrc *end_block, ResultLoc *parent, IrInstSrc *is_comptime) +{ + ResultLocPeerParent *peer_parent = heap::c_allocator.create(); + peer_parent->base.id = ResultLocIdPeerParent; + peer_parent->base.source_instruction = cond_br_inst; + peer_parent->base.allow_write_through_const = parent->allow_write_through_const; + peer_parent->end_bb = end_block; + peer_parent->is_comptime = is_comptime; + peer_parent->parent = parent; + + IrInstSrc *popped_inst = irb->current_basic_block->instruction_list.pop(); + ir_assert(popped_inst == cond_br_inst, &cond_br_inst->base); + + ir_build_reset_result(irb, cond_br_inst->base.scope, cond_br_inst->base.source_node, &peer_parent->base); + irb->current_basic_block->instruction_list.append(popped_inst); + + return peer_parent; +} + +static ResultLocPeerParent *ir_build_binary_result_peers(IrBuilderSrc *irb, IrInstSrc *cond_br_inst, + IrBasicBlockSrc *else_block, IrBasicBlockSrc *end_block, ResultLoc *parent, IrInstSrc *is_comptime) +{ + ResultLocPeerParent *peer_parent = ir_build_result_peers(irb, cond_br_inst, end_block, parent, is_comptime); + + peer_parent->peers.append(create_peer_result(peer_parent)); + peer_parent->peers.last()->next_bb = else_block; + + peer_parent->peers.append(create_peer_result(peer_parent)); + peer_parent->peers.last()->next_bb = end_block; + + return peer_parent; +} + +static IrInstSrc *ir_gen_orelse(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node, LVal lval, + ResultLoc *result_loc) +{ + assert(node->type == NodeTypeBinOpExpr); + + AstNode *op1_node = node->data.bin_op_expr.op1; + AstNode *op2_node = node->data.bin_op_expr.op2; + + IrInstSrc *maybe_ptr = ir_gen_node_extra(irb, op1_node, parent_scope, LValPtr, nullptr); + if (maybe_ptr == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + + IrInstSrc *maybe_val = ir_build_load_ptr(irb, parent_scope, node, maybe_ptr); + IrInstSrc *is_non_null = ir_build_test_non_null_src(irb, parent_scope, node, maybe_val); + + IrInstSrc *is_comptime; + if (ir_should_inline(irb->exec, parent_scope)) { + is_comptime = ir_build_const_bool(irb, parent_scope, node, true); + } else { + is_comptime = ir_build_test_comptime(irb, parent_scope, node, is_non_null); + } + + IrBasicBlockSrc *ok_block = ir_create_basic_block(irb, parent_scope, "OptionalNonNull"); + IrBasicBlockSrc *null_block = ir_create_basic_block(irb, parent_scope, "OptionalNull"); + IrBasicBlockSrc *end_block = ir_create_basic_block(irb, parent_scope, "OptionalEnd"); + IrInstSrc *cond_br_inst = ir_build_cond_br(irb, parent_scope, node, is_non_null, ok_block, null_block, is_comptime); + + ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, ok_block, end_block, + result_loc, is_comptime); + + ir_set_cursor_at_end_and_append_block(irb, null_block); + IrInstSrc *null_result = ir_gen_node_extra(irb, op2_node, parent_scope, LValNone, + &peer_parent->peers.at(0)->base); + if (null_result == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + IrBasicBlockSrc *after_null_block = irb->current_basic_block; + if (!instr_is_unreachable(null_result)) + ir_mark_gen(ir_build_br(irb, parent_scope, node, end_block, is_comptime)); + + ir_set_cursor_at_end_and_append_block(irb, ok_block); + IrInstSrc *unwrapped_ptr = ir_build_optional_unwrap_ptr(irb, parent_scope, node, maybe_ptr, false); + IrInstSrc *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr); + ir_build_end_expr(irb, parent_scope, node, unwrapped_payload, &peer_parent->peers.at(1)->base); + IrBasicBlockSrc *after_ok_block = irb->current_basic_block; + ir_build_br(irb, parent_scope, node, end_block, is_comptime); + + ir_set_cursor_at_end_and_append_block(irb, end_block); + IrInstSrc **incoming_values = heap::c_allocator.allocate(2); + incoming_values[0] = null_result; + incoming_values[1] = unwrapped_payload; + IrBasicBlockSrc **incoming_blocks = heap::c_allocator.allocate(2); + incoming_blocks[0] = after_null_block; + incoming_blocks[1] = after_ok_block; + IrInstSrc *phi = ir_build_phi(irb, parent_scope, node, 2, incoming_blocks, incoming_values, peer_parent); + return ir_lval_wrap(irb, parent_scope, phi, lval, result_loc); +} + +static IrInstSrc *ir_gen_error_union(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node) { + assert(node->type == NodeTypeBinOpExpr); + + AstNode *op1_node = node->data.bin_op_expr.op1; + AstNode *op2_node = node->data.bin_op_expr.op2; + + IrInstSrc *err_set = ir_gen_node(irb, op1_node, parent_scope); + if (err_set == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + + IrInstSrc *payload = ir_gen_node(irb, op2_node, parent_scope); + if (payload == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + + return ir_build_error_union(irb, parent_scope, node, err_set, payload); +} + +static IrInstSrc *ir_gen_bin_op(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { + assert(node->type == NodeTypeBinOpExpr); + + BinOpType bin_op_type = node->data.bin_op_expr.bin_op; + switch (bin_op_type) { + case BinOpTypeInvalid: + zig_unreachable(); + case BinOpTypeAssign: + return ir_lval_wrap(irb, scope, ir_gen_assign(irb, scope, node), lval, result_loc); + case BinOpTypeAssignTimes: + return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpMult), lval, result_loc); + case BinOpTypeAssignTimesWrap: + return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpMultWrap), lval, result_loc); + case BinOpTypeAssignDiv: + return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpDivUnspecified), lval, result_loc); + case BinOpTypeAssignMod: + return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpRemUnspecified), lval, result_loc); + case BinOpTypeAssignPlus: + return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpAdd), lval, result_loc); + case BinOpTypeAssignPlusWrap: + return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpAddWrap), lval, result_loc); + case BinOpTypeAssignMinus: + return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpSub), lval, result_loc); + case BinOpTypeAssignMinusWrap: + return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpSubWrap), lval, result_loc); + case BinOpTypeAssignBitShiftLeft: + return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpBitShiftLeftLossy), lval, result_loc); + case BinOpTypeAssignBitShiftRight: + return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpBitShiftRightLossy), lval, result_loc); + case BinOpTypeAssignBitAnd: + return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpBinAnd), lval, result_loc); + case BinOpTypeAssignBitXor: + return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpBinXor), lval, result_loc); + case BinOpTypeAssignBitOr: + return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpBinOr), lval, result_loc); + case BinOpTypeBoolOr: + return ir_lval_wrap(irb, scope, ir_gen_bool_or(irb, scope, node), lval, result_loc); + case BinOpTypeBoolAnd: + return ir_lval_wrap(irb, scope, ir_gen_bool_and(irb, scope, node), lval, result_loc); + case BinOpTypeCmpEq: + return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpEq), lval, result_loc); + case BinOpTypeCmpNotEq: + return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpNotEq), lval, result_loc); + case BinOpTypeCmpLessThan: + return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpLessThan), lval, result_loc); + case BinOpTypeCmpGreaterThan: + return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpGreaterThan), lval, result_loc); + case BinOpTypeCmpLessOrEq: + return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpLessOrEq), lval, result_loc); + case BinOpTypeCmpGreaterOrEq: + return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpGreaterOrEq), lval, result_loc); + case BinOpTypeBinOr: + return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpBinOr), lval, result_loc); + case BinOpTypeBinXor: + return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpBinXor), lval, result_loc); + case BinOpTypeBinAnd: + return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpBinAnd), lval, result_loc); + case BinOpTypeBitShiftLeft: + return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpBitShiftLeftLossy), lval, result_loc); + case BinOpTypeBitShiftRight: + return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpBitShiftRightLossy), lval, result_loc); + case BinOpTypeAdd: + return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpAdd), lval, result_loc); + case BinOpTypeAddWrap: + return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpAddWrap), lval, result_loc); + case BinOpTypeSub: + return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpSub), lval, result_loc); + case BinOpTypeSubWrap: + return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpSubWrap), lval, result_loc); + case BinOpTypeMult: + return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpMult), lval, result_loc); + case BinOpTypeMultWrap: + return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpMultWrap), lval, result_loc); + case BinOpTypeDiv: + return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpDivUnspecified), lval, result_loc); + case BinOpTypeMod: + return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpRemUnspecified), lval, result_loc); + case BinOpTypeArrayCat: + return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpArrayCat), lval, result_loc); + case BinOpTypeArrayMult: + return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpArrayMult), lval, result_loc); + case BinOpTypeMergeErrorSets: + return ir_lval_wrap(irb, scope, ir_gen_merge_err_sets(irb, scope, node), lval, result_loc); + case BinOpTypeUnwrapOptional: + return ir_gen_orelse(irb, scope, node, lval, result_loc); + case BinOpTypeErrorUnion: + return ir_lval_wrap(irb, scope, ir_gen_error_union(irb, scope, node), lval, result_loc); + } + zig_unreachable(); +} + +static IrInstSrc *ir_gen_int_lit(IrBuilderSrc *irb, Scope *scope, AstNode *node) { + assert(node->type == NodeTypeIntLiteral); + + RootStruct *root_struct = node->owner->data.structure.root_struct; + BigInt bigint; + token_number_literal_bigint(root_struct, &bigint, node->main_token); + return ir_build_const_bigint(irb, scope, node, bigint); +} + +static IrInstSrc *ir_gen_float_lit(IrBuilderSrc *irb, Scope *scope, AstNode *node) { + Error err; + assert(node->type == NodeTypeFloatLiteral); + + RootStruct *root_struct = node->owner->data.structure.root_struct; + const char *source = buf_ptr(root_struct->source_code); + uint32_t byte_offset = root_struct->token_locs[node->main_token].offset; + + BigFloat bigfloat; + if ((err = bigfloat_init_buf(&bigfloat, (const uint8_t *)source + byte_offset))) { + add_node_error(irb->codegen, node, buf_sprintf("float literal out of range of any type")); + return irb->codegen->invalid_inst_src; + } + + return ir_build_const_bigfloat(irb, scope, node, bigfloat); +} + +static IrInstSrc *ir_gen_char_lit(IrBuilderSrc *irb, Scope *scope, AstNode *node) { + Error err; + assert(node->type == NodeTypeCharLiteral); + + RootStruct *root_struct = node->owner->data.structure.root_struct; + const char *source = buf_ptr(root_struct->source_code); + uint32_t byte_offset = root_struct->token_locs[node->main_token].offset; + + src_assert(source[byte_offset] == '\'', node); + byte_offset += 1; + + uint32_t codepoint; + size_t bad_index; + if ((err = source_char_literal(source + byte_offset, &codepoint, &bad_index))) { + add_node_error(irb->codegen, node, buf_sprintf("invalid character")); + return irb->codegen->invalid_inst_src; + } + return ir_build_const_uint(irb, scope, node, codepoint); +} + +static IrInstSrc *ir_gen_null_literal(IrBuilderSrc *irb, Scope *scope, AstNode *node) { + assert(node->type == NodeTypeNullLiteral); + + return ir_build_const_null(irb, scope, node); +} + +static IrInstSrc *ir_gen_symbol(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { + Error err; + assert(node->type == NodeTypeIdentifier); + + Buf *variable_name = node_identifier_buf(node); + + if (buf_eql_str(variable_name, "_")) { + if (lval == LValAssign) { + IrInstSrcConst *const_instruction = ir_build_instruction(irb, scope, node); + const_instruction->value = irb->codegen->pass1_arena->create(); + const_instruction->value->type = get_pointer_to_type(irb->codegen, + irb->codegen->builtin_types.entry_void, false); + const_instruction->value->special = ConstValSpecialStatic; + const_instruction->value->data.x_ptr.special = ConstPtrSpecialDiscard; + return &const_instruction->base; + } else { + add_node_error(irb->codegen, node, buf_sprintf("`_` may only be used to assign things to")); + return irb->codegen->invalid_inst_src; + } + } + + ZigType *primitive_type; + if ((err = get_primitive_type(irb->codegen, variable_name, &primitive_type))) { + if (err == ErrorOverflow) { + add_node_error(irb->codegen, node, + buf_sprintf("primitive integer type '%s' exceeds maximum bit width of 65535", + buf_ptr(variable_name))); + return irb->codegen->invalid_inst_src; + } + assert(err == ErrorPrimitiveTypeNotFound); + } else { + IrInstSrc *value = ir_build_const_type(irb, scope, node, primitive_type); + if (lval == LValPtr || lval == LValAssign) { + return ir_build_ref_src(irb, scope, node, value); + } else { + return ir_expr_wrap(irb, scope, value, result_loc); + } + } + + ScopeFnDef *crossed_fndef_scope; + ZigVar *var = find_variable(irb->codegen, scope, variable_name, &crossed_fndef_scope); + if (var) { + IrInstSrc *var_ptr = ir_build_var_ptr_x(irb, scope, node, var, crossed_fndef_scope); + if (lval == LValPtr || lval == LValAssign) { + return var_ptr; + } else { + return ir_expr_wrap(irb, scope, ir_build_load_ptr(irb, scope, node, var_ptr), result_loc); + } + } + + Tld *tld = find_decl(irb->codegen, scope, variable_name); + if (tld) { + IrInstSrc *decl_ref = ir_build_decl_ref(irb, scope, node, tld, lval); + if (lval == LValPtr || lval == LValAssign) { + return decl_ref; + } else { + return ir_expr_wrap(irb, scope, decl_ref, result_loc); + } + } + + if (get_container_scope(node->owner)->any_imports_failed) { + // skip the error message since we had a failing import in this file + // if an import breaks we don't need redundant undeclared identifier errors + return irb->codegen->invalid_inst_src; + } + + return ir_build_undeclared_identifier(irb, scope, node, variable_name); +} + +static IrInstSrc *ir_gen_array_access(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, + ResultLoc *result_loc) +{ + assert(node->type == NodeTypeArrayAccessExpr); + + AstNode *array_ref_node = node->data.array_access_expr.array_ref_expr; + IrInstSrc *array_ref_instruction = ir_gen_node_extra(irb, array_ref_node, scope, LValPtr, nullptr); + if (array_ref_instruction == irb->codegen->invalid_inst_src) + return array_ref_instruction; + + // Create an usize-typed result location to hold the subscript value, this + // makes it possible for the compiler to infer the subscript expression type + // if needed + IrInstSrc *usize_type_inst = ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_usize); + ResultLocCast *result_loc_cast = ir_build_cast_result_loc(irb, usize_type_inst, no_result_loc()); + + AstNode *subscript_node = node->data.array_access_expr.subscript; + IrInstSrc *subscript_value = ir_gen_node_extra(irb, subscript_node, scope, LValNone, &result_loc_cast->base); + if (subscript_value == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + + IrInstSrc *subscript_instruction = ir_build_implicit_cast(irb, scope, subscript_node, subscript_value, result_loc_cast); + + IrInstSrc *ptr_instruction = ir_build_elem_ptr(irb, scope, node, array_ref_instruction, + subscript_instruction, true, PtrLenSingle, nullptr); + if (lval == LValPtr || lval == LValAssign) + return ptr_instruction; + + IrInstSrc *load_ptr = ir_build_load_ptr(irb, scope, node, ptr_instruction); + return ir_expr_wrap(irb, scope, load_ptr, result_loc); +} + +static IrInstSrc *ir_gen_field_access(IrBuilderSrc *irb, Scope *scope, AstNode *node) { + assert(node->type == NodeTypeFieldAccessExpr); + + AstNode *container_ref_node = node->data.field_access_expr.struct_expr; + Buf *field_name = node->data.field_access_expr.field_name; + + IrInstSrc *container_ref_instruction = ir_gen_node_extra(irb, container_ref_node, scope, LValPtr, nullptr); + if (container_ref_instruction == irb->codegen->invalid_inst_src) + return container_ref_instruction; + + return ir_build_field_ptr(irb, scope, node, container_ref_instruction, field_name, false); +} + +static IrInstSrc *ir_gen_overflow_op(IrBuilderSrc *irb, Scope *scope, AstNode *node, IrOverflowOp op) { + assert(node->type == NodeTypeFnCallExpr); + + AstNode *type_node = node->data.fn_call_expr.params.at(0); + AstNode *op1_node = node->data.fn_call_expr.params.at(1); + AstNode *op2_node = node->data.fn_call_expr.params.at(2); + AstNode *result_ptr_node = node->data.fn_call_expr.params.at(3); + + + IrInstSrc *type_value = ir_gen_node(irb, type_node, scope); + if (type_value == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + + IrInstSrc *op1 = ir_gen_node(irb, op1_node, scope); + if (op1 == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + + IrInstSrc *op2 = ir_gen_node(irb, op2_node, scope); + if (op2 == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + + IrInstSrc *result_ptr = ir_gen_node(irb, result_ptr_node, scope); + if (result_ptr == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + + return ir_build_overflow_op_src(irb, scope, node, op, type_value, op1, op2, result_ptr); +} + +static IrInstSrc *ir_gen_mul_add(IrBuilderSrc *irb, Scope *scope, AstNode *node) { + assert(node->type == NodeTypeFnCallExpr); + + AstNode *type_node = node->data.fn_call_expr.params.at(0); + AstNode *op1_node = node->data.fn_call_expr.params.at(1); + AstNode *op2_node = node->data.fn_call_expr.params.at(2); + AstNode *op3_node = node->data.fn_call_expr.params.at(3); + + IrInstSrc *type_value = ir_gen_node(irb, type_node, scope); + if (type_value == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + + IrInstSrc *op1 = ir_gen_node(irb, op1_node, scope); + if (op1 == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + + IrInstSrc *op2 = ir_gen_node(irb, op2_node, scope); + if (op2 == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + + IrInstSrc *op3 = ir_gen_node(irb, op3_node, scope); + if (op3 == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + + return ir_build_mul_add_src(irb, scope, node, type_value, op1, op2, op3); +} + +static IrInstSrc *ir_gen_this(IrBuilderSrc *irb, Scope *orig_scope, AstNode *node) { + for (Scope *it_scope = orig_scope; it_scope != nullptr; it_scope = it_scope->parent) { + if (it_scope->id == ScopeIdDecls) { + ScopeDecls *decls_scope = (ScopeDecls *)it_scope; + ZigType *container_type = decls_scope->container_type; + if (container_type != nullptr) { + return ir_build_const_type(irb, orig_scope, node, container_type); + } else { + return ir_build_const_import(irb, orig_scope, node, decls_scope->import); + } + } + } + zig_unreachable(); +} + +static IrInstSrc *ir_gen_async_call(IrBuilderSrc *irb, Scope *scope, AstNode *await_node, AstNode *call_node, + LVal lval, ResultLoc *result_loc) +{ + if (call_node->data.fn_call_expr.params.length != 4) { + add_node_error(irb->codegen, call_node, + buf_sprintf("expected 4 arguments, found %" ZIG_PRI_usize, + call_node->data.fn_call_expr.params.length)); + return irb->codegen->invalid_inst_src; + } + + AstNode *bytes_node = call_node->data.fn_call_expr.params.at(0); + IrInstSrc *bytes = ir_gen_node(irb, bytes_node, scope); + if (bytes == irb->codegen->invalid_inst_src) + return bytes; + + AstNode *ret_ptr_node = call_node->data.fn_call_expr.params.at(1); + IrInstSrc *ret_ptr = ir_gen_node(irb, ret_ptr_node, scope); + if (ret_ptr == irb->codegen->invalid_inst_src) + return ret_ptr; + + AstNode *fn_ref_node = call_node->data.fn_call_expr.params.at(2); + IrInstSrc *fn_ref = ir_gen_node(irb, fn_ref_node, scope); + if (fn_ref == irb->codegen->invalid_inst_src) + return fn_ref; + + CallModifier modifier = (await_node == nullptr) ? CallModifierAsync : CallModifierNone; + bool is_async_call_builtin = true; + AstNode *args_node = call_node->data.fn_call_expr.params.at(3); + if (args_node->type == NodeTypeContainerInitExpr) { + if (args_node->data.container_init_expr.kind == ContainerInitKindArray || + args_node->data.container_init_expr.entries.length == 0) + { + size_t arg_count = args_node->data.container_init_expr.entries.length; + IrInstSrc **args = heap::c_allocator.allocate(arg_count); + for (size_t i = 0; i < arg_count; i += 1) { + AstNode *arg_node = args_node->data.container_init_expr.entries.at(i); + IrInstSrc *arg = ir_gen_node(irb, arg_node, scope); + if (arg == irb->codegen->invalid_inst_src) + return arg; + args[i] = arg; + } + + IrInstSrc *call = ir_build_call_src(irb, scope, call_node, nullptr, fn_ref, arg_count, args, + ret_ptr, modifier, is_async_call_builtin, bytes, result_loc); + return ir_lval_wrap(irb, scope, call, lval, result_loc); + } else { + exec_add_error_node(irb->codegen, irb->exec, args_node, + buf_sprintf("TODO: @asyncCall with anon struct literal")); + return irb->codegen->invalid_inst_src; + } + } + IrInstSrc *args = ir_gen_node(irb, args_node, scope); + if (args == irb->codegen->invalid_inst_src) + return args; + + IrInstSrc *call = ir_build_async_call_extra(irb, scope, call_node, modifier, fn_ref, ret_ptr, bytes, args, result_loc); + return ir_lval_wrap(irb, scope, call, lval, result_loc); +} + +static IrInstSrc *ir_gen_fn_call_with_args(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + AstNode *fn_ref_node, CallModifier modifier, IrInstSrc *options, + AstNode **args_ptr, size_t args_len, LVal lval, ResultLoc *result_loc) +{ + IrInstSrc *fn_ref = ir_gen_node(irb, fn_ref_node, scope); + if (fn_ref == irb->codegen->invalid_inst_src) + return fn_ref; + + IrInstSrc *fn_type = ir_build_typeof_1(irb, scope, source_node, fn_ref); + + IrInstSrc **args = heap::c_allocator.allocate(args_len); + for (size_t i = 0; i < args_len; i += 1) { + AstNode *arg_node = args_ptr[i]; + + IrInstSrc *arg_index = ir_build_const_usize(irb, scope, arg_node, i); + IrInstSrc *arg_type = ir_build_arg_type(irb, scope, source_node, fn_type, arg_index, true); + ResultLoc *no_result = no_result_loc(); + ir_build_reset_result(irb, scope, source_node, no_result); + ResultLocCast *result_loc_cast = ir_build_cast_result_loc(irb, arg_type, no_result); + + IrInstSrc *arg = ir_gen_node_extra(irb, arg_node, scope, LValNone, &result_loc_cast->base); + if (arg == irb->codegen->invalid_inst_src) + return arg; + + args[i] = ir_build_implicit_cast(irb, scope, arg_node, arg, result_loc_cast); + } + + IrInstSrc *fn_call; + if (options != nullptr) { + fn_call = ir_build_call_args(irb, scope, source_node, options, fn_ref, args, args_len, result_loc); + } else { + fn_call = ir_build_call_src(irb, scope, source_node, nullptr, fn_ref, args_len, args, nullptr, + modifier, false, nullptr, result_loc); + } + return ir_lval_wrap(irb, scope, fn_call, lval, result_loc); +} + +static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, + ResultLoc *result_loc) +{ + assert(node->type == NodeTypeFnCallExpr); + + AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr; + Buf *name = node_identifier_buf(fn_ref_expr); + auto entry = irb->codegen->builtin_fn_table.maybe_get(name); + + if (!entry) { + add_node_error(irb->codegen, node, + buf_sprintf("invalid builtin function: '%s'", buf_ptr(name))); + return irb->codegen->invalid_inst_src; + } + + BuiltinFnEntry *builtin_fn = entry->value; + size_t actual_param_count = node->data.fn_call_expr.params.length; + + if (builtin_fn->param_count != SIZE_MAX && builtin_fn->param_count != actual_param_count) { + add_node_error(irb->codegen, node, + buf_sprintf("expected %" ZIG_PRI_usize " argument(s), found %" ZIG_PRI_usize, + builtin_fn->param_count, actual_param_count)); + return irb->codegen->invalid_inst_src; + } + + switch (builtin_fn->id) { + case BuiltinFnIdInvalid: + zig_unreachable(); + case BuiltinFnIdTypeof: + { + Scope *sub_scope = create_typeof_scope(irb->codegen, node, scope); + + size_t arg_count = node->data.fn_call_expr.params.length; + + IrInstSrc *type_of; + + if (arg_count == 0) { + add_node_error(irb->codegen, node, + buf_sprintf("expected at least 1 argument, found 0")); + return irb->codegen->invalid_inst_src; + } else if (arg_count == 1) { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, sub_scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + type_of = ir_build_typeof_1(irb, scope, node, arg0_value); + } else { + IrInstSrc **args = heap::c_allocator.allocate(arg_count); + for (size_t i = 0; i < arg_count; i += 1) { + AstNode *arg_node = node->data.fn_call_expr.params.at(i); + IrInstSrc *arg = ir_gen_node(irb, arg_node, sub_scope); + if (arg == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + args[i] = arg; + } + + type_of = ir_build_typeof_n(irb, scope, node, args, arg_count); + } + return ir_lval_wrap(irb, scope, type_of, lval, result_loc); + } + case BuiltinFnIdSetCold: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + IrInstSrc *set_cold = ir_build_set_cold(irb, scope, node, arg0_value); + return ir_lval_wrap(irb, scope, set_cold, lval, result_loc); + } + case BuiltinFnIdSetRuntimeSafety: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + IrInstSrc *set_safety = ir_build_set_runtime_safety(irb, scope, node, arg0_value); + return ir_lval_wrap(irb, scope, set_safety, lval, result_loc); + } + case BuiltinFnIdSetFloatMode: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + IrInstSrc *set_float_mode = ir_build_set_float_mode(irb, scope, node, arg0_value); + return ir_lval_wrap(irb, scope, set_float_mode, lval, result_loc); + } + case BuiltinFnIdSizeof: + case BuiltinFnIdBitSizeof: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + IrInstSrc *size_of = ir_build_size_of(irb, scope, node, arg0_value, builtin_fn->id == BuiltinFnIdBitSizeof); + return ir_lval_wrap(irb, scope, size_of, lval, result_loc); + } + case BuiltinFnIdImport: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + IrInstSrc *import = ir_build_import(irb, scope, node, arg0_value); + return ir_lval_wrap(irb, scope, import, lval, result_loc); + } + case BuiltinFnIdCImport: + { + IrInstSrc *c_import = ir_build_c_import(irb, scope, node); + return ir_lval_wrap(irb, scope, c_import, lval, result_loc); + } + case BuiltinFnIdCInclude: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + if (!exec_c_import_buf(irb->exec)) { + add_node_error(irb->codegen, node, buf_sprintf("C include valid only inside C import block")); + return irb->codegen->invalid_inst_src; + } + + IrInstSrc *c_include = ir_build_c_include(irb, scope, node, arg0_value); + return ir_lval_wrap(irb, scope, c_include, lval, result_loc); + } + case BuiltinFnIdCDefine: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) + return arg1_value; + + if (!exec_c_import_buf(irb->exec)) { + add_node_error(irb->codegen, node, buf_sprintf("C define valid only inside C import block")); + return irb->codegen->invalid_inst_src; + } + + IrInstSrc *c_define = ir_build_c_define(irb, scope, node, arg0_value, arg1_value); + return ir_lval_wrap(irb, scope, c_define, lval, result_loc); + } + case BuiltinFnIdCUndef: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + if (!exec_c_import_buf(irb->exec)) { + add_node_error(irb->codegen, node, buf_sprintf("C undef valid only inside C import block")); + return irb->codegen->invalid_inst_src; + } + + IrInstSrc *c_undef = ir_build_c_undef(irb, scope, node, arg0_value); + return ir_lval_wrap(irb, scope, c_undef, lval, result_loc); + } + case BuiltinFnIdCompileErr: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + IrInstSrc *compile_err = ir_build_compile_err(irb, scope, node, arg0_value); + return ir_lval_wrap(irb, scope, compile_err, lval, result_loc); + } + case BuiltinFnIdCompileLog: + { + IrInstSrc **args = heap::c_allocator.allocate(actual_param_count); + + for (size_t i = 0; i < actual_param_count; i += 1) { + AstNode *arg_node = node->data.fn_call_expr.params.at(i); + args[i] = ir_gen_node(irb, arg_node, scope); + if (args[i] == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + } + + IrInstSrc *compile_log = ir_build_compile_log(irb, scope, node, actual_param_count, args); + return ir_lval_wrap(irb, scope, compile_log, lval, result_loc); + } + case BuiltinFnIdErrName: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + IrInstSrc *err_name = ir_build_err_name(irb, scope, node, arg0_value); + return ir_lval_wrap(irb, scope, err_name, lval, result_loc); + } + case BuiltinFnIdEmbedFile: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + IrInstSrc *embed_file = ir_build_embed_file(irb, scope, node, arg0_value); + return ir_lval_wrap(irb, scope, embed_file, lval, result_loc); + } + case BuiltinFnIdCmpxchgWeak: + case BuiltinFnIdCmpxchgStrong: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) + return arg1_value; + + AstNode *arg2_node = node->data.fn_call_expr.params.at(2); + IrInstSrc *arg2_value = ir_gen_node(irb, arg2_node, scope); + if (arg2_value == irb->codegen->invalid_inst_src) + return arg2_value; + + AstNode *arg3_node = node->data.fn_call_expr.params.at(3); + IrInstSrc *arg3_value = ir_gen_node(irb, arg3_node, scope); + if (arg3_value == irb->codegen->invalid_inst_src) + return arg3_value; + + AstNode *arg4_node = node->data.fn_call_expr.params.at(4); + IrInstSrc *arg4_value = ir_gen_node(irb, arg4_node, scope); + if (arg4_value == irb->codegen->invalid_inst_src) + return arg4_value; + + AstNode *arg5_node = node->data.fn_call_expr.params.at(5); + IrInstSrc *arg5_value = ir_gen_node(irb, arg5_node, scope); + if (arg5_value == irb->codegen->invalid_inst_src) + return arg5_value; + + IrInstSrc *cmpxchg = ir_build_cmpxchg_src(irb, scope, node, arg0_value, arg1_value, + arg2_value, arg3_value, arg4_value, arg5_value, (builtin_fn->id == BuiltinFnIdCmpxchgWeak), + result_loc); + return ir_lval_wrap(irb, scope, cmpxchg, lval, result_loc); + } + case BuiltinFnIdFence: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + IrInstSrc *fence = ir_build_fence(irb, scope, node, arg0_value); + return ir_lval_wrap(irb, scope, fence, lval, result_loc); + } + case BuiltinFnIdReduce: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) + return arg1_value; + + IrInstSrc *reduce = ir_build_reduce(irb, scope, node, arg0_value, arg1_value); + return ir_lval_wrap(irb, scope, reduce, lval, result_loc); + } + case BuiltinFnIdDivExact: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) + return arg1_value; + + IrInstSrc *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpDivExact, arg0_value, arg1_value, true); + return ir_lval_wrap(irb, scope, bin_op, lval, result_loc); + } + case BuiltinFnIdDivTrunc: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) + return arg1_value; + + IrInstSrc *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpDivTrunc, arg0_value, arg1_value, true); + return ir_lval_wrap(irb, scope, bin_op, lval, result_loc); + } + case BuiltinFnIdDivFloor: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) + return arg1_value; + + IrInstSrc *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpDivFloor, arg0_value, arg1_value, true); + return ir_lval_wrap(irb, scope, bin_op, lval, result_loc); + } + case BuiltinFnIdRem: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) + return arg1_value; + + IrInstSrc *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpRemRem, arg0_value, arg1_value, true); + return ir_lval_wrap(irb, scope, bin_op, lval, result_loc); + } + case BuiltinFnIdMod: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) + return arg1_value; + + IrInstSrc *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpRemMod, arg0_value, arg1_value, true); + return ir_lval_wrap(irb, scope, bin_op, lval, result_loc); + } + case BuiltinFnIdSqrt: + case BuiltinFnIdSin: + case BuiltinFnIdCos: + case BuiltinFnIdExp: + case BuiltinFnIdExp2: + case BuiltinFnIdLog: + case BuiltinFnIdLog2: + case BuiltinFnIdLog10: + case BuiltinFnIdFabs: + case BuiltinFnIdFloor: + case BuiltinFnIdCeil: + case BuiltinFnIdTrunc: + case BuiltinFnIdNearbyInt: + case BuiltinFnIdRound: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + IrInstSrc *inst = ir_build_float_op_src(irb, scope, node, arg0_value, builtin_fn->id); + return ir_lval_wrap(irb, scope, inst, lval, result_loc); + } + case BuiltinFnIdTruncate: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) + return arg1_value; + + IrInstSrc *truncate = ir_build_truncate(irb, scope, node, arg0_value, arg1_value); + return ir_lval_wrap(irb, scope, truncate, lval, result_loc); + } + case BuiltinFnIdIntCast: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) + return arg1_value; + + IrInstSrc *result = ir_build_int_cast(irb, scope, node, arg0_value, arg1_value); + return ir_lval_wrap(irb, scope, result, lval, result_loc); + } + case BuiltinFnIdFloatCast: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) + return arg1_value; + + IrInstSrc *result = ir_build_float_cast(irb, scope, node, arg0_value, arg1_value); + return ir_lval_wrap(irb, scope, result, lval, result_loc); + } + case BuiltinFnIdErrSetCast: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) + return arg1_value; + + IrInstSrc *result = ir_build_err_set_cast(irb, scope, node, arg0_value, arg1_value); + return ir_lval_wrap(irb, scope, result, lval, result_loc); + } + case BuiltinFnIdIntToFloat: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) + return arg1_value; + + IrInstSrc *result = ir_build_int_to_float(irb, scope, node, arg0_value, arg1_value); + return ir_lval_wrap(irb, scope, result, lval, result_loc); + } + case BuiltinFnIdFloatToInt: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) + return arg1_value; + + IrInstSrc *result = ir_build_float_to_int(irb, scope, node, arg0_value, arg1_value); + return ir_lval_wrap(irb, scope, result, lval, result_loc); + } + case BuiltinFnIdErrToInt: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + IrInstSrc *result = ir_build_err_to_int_src(irb, scope, node, arg0_value); + return ir_lval_wrap(irb, scope, result, lval, result_loc); + } + case BuiltinFnIdIntToErr: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + IrInstSrc *result = ir_build_int_to_err_src(irb, scope, node, arg0_value); + return ir_lval_wrap(irb, scope, result, lval, result_loc); + } + case BuiltinFnIdBoolToInt: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + IrInstSrc *result = ir_build_bool_to_int(irb, scope, node, arg0_value); + return ir_lval_wrap(irb, scope, result, lval, result_loc); + } + case BuiltinFnIdVectorType: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) + return arg1_value; + + IrInstSrc *vector_type = ir_build_vector_type(irb, scope, node, arg0_value, arg1_value); + return ir_lval_wrap(irb, scope, vector_type, lval, result_loc); + } + case BuiltinFnIdShuffle: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) + return arg1_value; + + AstNode *arg2_node = node->data.fn_call_expr.params.at(2); + IrInstSrc *arg2_value = ir_gen_node(irb, arg2_node, scope); + if (arg2_value == irb->codegen->invalid_inst_src) + return arg2_value; + + AstNode *arg3_node = node->data.fn_call_expr.params.at(3); + IrInstSrc *arg3_value = ir_gen_node(irb, arg3_node, scope); + if (arg3_value == irb->codegen->invalid_inst_src) + return arg3_value; + + IrInstSrc *shuffle_vector = ir_build_shuffle_vector(irb, scope, node, + arg0_value, arg1_value, arg2_value, arg3_value); + return ir_lval_wrap(irb, scope, shuffle_vector, lval, result_loc); + } + case BuiltinFnIdSplat: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) + return arg1_value; + + IrInstSrc *splat = ir_build_splat_src(irb, scope, node, + arg0_value, arg1_value); + return ir_lval_wrap(irb, scope, splat, lval, result_loc); + } + case BuiltinFnIdMemcpy: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) + return arg1_value; + + AstNode *arg2_node = node->data.fn_call_expr.params.at(2); + IrInstSrc *arg2_value = ir_gen_node(irb, arg2_node, scope); + if (arg2_value == irb->codegen->invalid_inst_src) + return arg2_value; + + IrInstSrc *ir_memcpy = ir_build_memcpy_src(irb, scope, node, arg0_value, arg1_value, arg2_value); + return ir_lval_wrap(irb, scope, ir_memcpy, lval, result_loc); + } + case BuiltinFnIdMemset: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) + return arg1_value; + + AstNode *arg2_node = node->data.fn_call_expr.params.at(2); + IrInstSrc *arg2_value = ir_gen_node(irb, arg2_node, scope); + if (arg2_value == irb->codegen->invalid_inst_src) + return arg2_value; + + IrInstSrc *ir_memset = ir_build_memset_src(irb, scope, node, arg0_value, arg1_value, arg2_value); + return ir_lval_wrap(irb, scope, ir_memset, lval, result_loc); + } + case BuiltinFnIdWasmMemorySize: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + IrInstSrc *ir_wasm_memory_size = ir_build_wasm_memory_size_src(irb, scope, node, arg0_value); + return ir_lval_wrap(irb, scope, ir_wasm_memory_size, lval, result_loc); + } + case BuiltinFnIdWasmMemoryGrow: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) + return arg1_value; + + IrInstSrc *ir_wasm_memory_grow = ir_build_wasm_memory_grow_src(irb, scope, node, arg0_value, arg1_value); + return ir_lval_wrap(irb, scope, ir_wasm_memory_grow, lval, result_loc); + } + case BuiltinFnIdField: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node_extra(irb, arg0_node, scope, LValPtr, nullptr); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) + return arg1_value; + + IrInstSrc *ptr_instruction = ir_build_field_ptr_instruction(irb, scope, node, + arg0_value, arg1_value, false); + + if (lval == LValPtr || lval == LValAssign) + return ptr_instruction; + + IrInstSrc *load_ptr = ir_build_load_ptr(irb, scope, node, ptr_instruction); + return ir_expr_wrap(irb, scope, load_ptr, result_loc); + } + case BuiltinFnIdHasField: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) + return arg1_value; + + IrInstSrc *type_info = ir_build_has_field(irb, scope, node, arg0_value, arg1_value); + return ir_lval_wrap(irb, scope, type_info, lval, result_loc); + } + case BuiltinFnIdTypeInfo: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + IrInstSrc *type_info = ir_build_type_info(irb, scope, node, arg0_value); + return ir_lval_wrap(irb, scope, type_info, lval, result_loc); + } + case BuiltinFnIdType: + { + AstNode *arg_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg = ir_gen_node(irb, arg_node, scope); + if (arg == irb->codegen->invalid_inst_src) + return arg; + + IrInstSrc *type = ir_build_type(irb, scope, node, arg); + return ir_lval_wrap(irb, scope, type, lval, result_loc); + } + case BuiltinFnIdBreakpoint: + return ir_lval_wrap(irb, scope, ir_build_breakpoint(irb, scope, node), lval, result_loc); + case BuiltinFnIdReturnAddress: + return ir_lval_wrap(irb, scope, ir_build_return_address_src(irb, scope, node), lval, result_loc); + case BuiltinFnIdFrameAddress: + return ir_lval_wrap(irb, scope, ir_build_frame_address_src(irb, scope, node), lval, result_loc); + case BuiltinFnIdFrameHandle: + if (!irb->exec->fn_entry) { + add_node_error(irb->codegen, node, buf_sprintf("@frame() called outside of function definition")); + return irb->codegen->invalid_inst_src; + } + return ir_lval_wrap(irb, scope, ir_build_handle_src(irb, scope, node), lval, result_loc); + case BuiltinFnIdFrameType: { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + IrInstSrc *frame_type = ir_build_frame_type(irb, scope, node, arg0_value); + return ir_lval_wrap(irb, scope, frame_type, lval, result_loc); + } + case BuiltinFnIdFrameSize: { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + IrInstSrc *frame_size = ir_build_frame_size_src(irb, scope, node, arg0_value); + return ir_lval_wrap(irb, scope, frame_size, lval, result_loc); + } + case BuiltinFnIdAlignOf: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + IrInstSrc *align_of = ir_build_align_of(irb, scope, node, arg0_value); + return ir_lval_wrap(irb, scope, align_of, lval, result_loc); + } + case BuiltinFnIdAddWithOverflow: + return ir_lval_wrap(irb, scope, ir_gen_overflow_op(irb, scope, node, IrOverflowOpAdd), lval, result_loc); + case BuiltinFnIdSubWithOverflow: + return ir_lval_wrap(irb, scope, ir_gen_overflow_op(irb, scope, node, IrOverflowOpSub), lval, result_loc); + case BuiltinFnIdMulWithOverflow: + return ir_lval_wrap(irb, scope, ir_gen_overflow_op(irb, scope, node, IrOverflowOpMul), lval, result_loc); + case BuiltinFnIdShlWithOverflow: + return ir_lval_wrap(irb, scope, ir_gen_overflow_op(irb, scope, node, IrOverflowOpShl), lval, result_loc); + case BuiltinFnIdMulAdd: + return ir_lval_wrap(irb, scope, ir_gen_mul_add(irb, scope, node), lval, result_loc); + case BuiltinFnIdTypeName: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + IrInstSrc *type_name = ir_build_type_name(irb, scope, node, arg0_value); + return ir_lval_wrap(irb, scope, type_name, lval, result_loc); + } + case BuiltinFnIdPanic: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + IrInstSrc *panic = ir_build_panic_src(irb, scope, node, arg0_value); + return ir_lval_wrap(irb, scope, panic, lval, result_loc); + } + case BuiltinFnIdPtrCast: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) + return arg1_value; + + IrInstSrc *ptr_cast = ir_build_ptr_cast_src(irb, scope, node, arg0_value, arg1_value, true); + return ir_lval_wrap(irb, scope, ptr_cast, lval, result_loc); + } + case BuiltinFnIdBitCast: + { + AstNode *dest_type_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *dest_type = ir_gen_node(irb, dest_type_node, scope); + if (dest_type == irb->codegen->invalid_inst_src) + return dest_type; + + ResultLocBitCast *result_loc_bit_cast = heap::c_allocator.create(); + result_loc_bit_cast->base.id = ResultLocIdBitCast; + result_loc_bit_cast->base.source_instruction = dest_type; + result_loc_bit_cast->base.allow_write_through_const = result_loc->allow_write_through_const; + ir_ref_instruction(dest_type, irb->current_basic_block); + result_loc_bit_cast->parent = result_loc; + + ir_build_reset_result(irb, scope, node, &result_loc_bit_cast->base); + + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstSrc *arg1_value = ir_gen_node_extra(irb, arg1_node, scope, LValNone, + &result_loc_bit_cast->base); + if (arg1_value == irb->codegen->invalid_inst_src) + return arg1_value; + + IrInstSrc *bitcast = ir_build_bit_cast_src(irb, scope, arg1_node, arg1_value, result_loc_bit_cast); + return ir_lval_wrap(irb, scope, bitcast, lval, result_loc); + } + case BuiltinFnIdAs: + { + AstNode *dest_type_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *dest_type = ir_gen_node(irb, dest_type_node, scope); + if (dest_type == irb->codegen->invalid_inst_src) + return dest_type; + + ResultLocCast *result_loc_cast = ir_build_cast_result_loc(irb, dest_type, result_loc); + + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstSrc *arg1_value = ir_gen_node_extra(irb, arg1_node, scope, LValNone, + &result_loc_cast->base); + if (arg1_value == irb->codegen->invalid_inst_src) + return arg1_value; + + IrInstSrc *result = ir_build_implicit_cast(irb, scope, node, arg1_value, result_loc_cast); + return ir_lval_wrap(irb, scope, result, lval, result_loc); + } + case BuiltinFnIdIntToPtr: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) + return arg1_value; + + IrInstSrc *int_to_ptr = ir_build_int_to_ptr_src(irb, scope, node, arg0_value, arg1_value); + return ir_lval_wrap(irb, scope, int_to_ptr, lval, result_loc); + } + case BuiltinFnIdPtrToInt: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + IrInstSrc *ptr_to_int = ir_build_ptr_to_int_src(irb, scope, node, arg0_value); + return ir_lval_wrap(irb, scope, ptr_to_int, lval, result_loc); + } + case BuiltinFnIdTagName: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + IrInstSrc *tag_name = ir_build_tag_name_src(irb, scope, node, arg0_value); + return ir_lval_wrap(irb, scope, tag_name, lval, result_loc); + } + case BuiltinFnIdFieldParentPtr: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) + return arg1_value; + + AstNode *arg2_node = node->data.fn_call_expr.params.at(2); + IrInstSrc *arg2_value = ir_gen_node(irb, arg2_node, scope); + if (arg2_value == irb->codegen->invalid_inst_src) + return arg2_value; + + IrInstSrc *field_parent_ptr = ir_build_field_parent_ptr_src(irb, scope, node, + arg0_value, arg1_value, arg2_value); + return ir_lval_wrap(irb, scope, field_parent_ptr, lval, result_loc); + } + case BuiltinFnIdByteOffsetOf: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) + return arg1_value; + + IrInstSrc *offset_of = ir_build_byte_offset_of(irb, scope, node, arg0_value, arg1_value); + return ir_lval_wrap(irb, scope, offset_of, lval, result_loc); + } + case BuiltinFnIdBitOffsetOf: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) + return arg1_value; + + IrInstSrc *offset_of = ir_build_bit_offset_of(irb, scope, node, arg0_value, arg1_value); + return ir_lval_wrap(irb, scope, offset_of, lval, result_loc); + } + case BuiltinFnIdCall: { + // Cast the options parameter to the options type + ZigType *options_type = get_builtin_type(irb->codegen, "CallOptions"); + IrInstSrc *options_type_inst = ir_build_const_type(irb, scope, node, options_type); + ResultLocCast *result_loc_cast = ir_build_cast_result_loc(irb, options_type_inst, no_result_loc()); + + AstNode *options_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *options_inner = ir_gen_node_extra(irb, options_node, scope, + LValNone, &result_loc_cast->base); + if (options_inner == irb->codegen->invalid_inst_src) + return options_inner; + IrInstSrc *options = ir_build_implicit_cast(irb, scope, options_node, options_inner, result_loc_cast); + + AstNode *fn_ref_node = node->data.fn_call_expr.params.at(1); + AstNode *args_node = node->data.fn_call_expr.params.at(2); + if (args_node->type == NodeTypeContainerInitExpr) { + if (args_node->data.container_init_expr.kind == ContainerInitKindArray || + args_node->data.container_init_expr.entries.length == 0) + { + return ir_gen_fn_call_with_args(irb, scope, node, + fn_ref_node, CallModifierNone, options, + args_node->data.container_init_expr.entries.items, + args_node->data.container_init_expr.entries.length, + lval, result_loc); + } else { + exec_add_error_node(irb->codegen, irb->exec, args_node, + buf_sprintf("TODO: @call with anon struct literal")); + return irb->codegen->invalid_inst_src; + } + } else { + IrInstSrc *fn_ref = ir_gen_node(irb, fn_ref_node, scope); + if (fn_ref == irb->codegen->invalid_inst_src) + return fn_ref; + + IrInstSrc *args = ir_gen_node(irb, args_node, scope); + if (args == irb->codegen->invalid_inst_src) + return args; + + IrInstSrc *call = ir_build_call_extra(irb, scope, node, options, fn_ref, args, result_loc); + return ir_lval_wrap(irb, scope, call, lval, result_loc); + } + } + case BuiltinFnIdAsyncCall: + return ir_gen_async_call(irb, scope, nullptr, node, lval, result_loc); + case BuiltinFnIdShlExact: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) + return arg1_value; + + IrInstSrc *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpBitShiftLeftExact, arg0_value, arg1_value, true); + return ir_lval_wrap(irb, scope, bin_op, lval, result_loc); + } + case BuiltinFnIdShrExact: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) + return arg1_value; + + IrInstSrc *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpBitShiftRightExact, arg0_value, arg1_value, true); + return ir_lval_wrap(irb, scope, bin_op, lval, result_loc); + } + case BuiltinFnIdSetEvalBranchQuota: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + IrInstSrc *set_eval_branch_quota = ir_build_set_eval_branch_quota(irb, scope, node, arg0_value); + return ir_lval_wrap(irb, scope, set_eval_branch_quota, lval, result_loc); + } + case BuiltinFnIdAlignCast: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) + return arg1_value; + + IrInstSrc *align_cast = ir_build_align_cast_src(irb, scope, node, arg0_value, arg1_value); + return ir_lval_wrap(irb, scope, align_cast, lval, result_loc); + } + case BuiltinFnIdThis: + { + IrInstSrc *this_inst = ir_gen_this(irb, scope, node); + return ir_lval_wrap(irb, scope, this_inst, lval, result_loc); + } + case BuiltinFnIdSetAlignStack: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + IrInstSrc *set_align_stack = ir_build_set_align_stack(irb, scope, node, arg0_value); + return ir_lval_wrap(irb, scope, set_align_stack, lval, result_loc); + } + case BuiltinFnIdExport: + { + // Cast the options parameter to the options type + ZigType *options_type = get_builtin_type(irb->codegen, "ExportOptions"); + IrInstSrc *options_type_inst = ir_build_const_type(irb, scope, node, options_type); + ResultLocCast *result_loc_cast = ir_build_cast_result_loc(irb, options_type_inst, no_result_loc()); + + AstNode *target_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *target_value = ir_gen_node(irb, target_node, scope); + if (target_value == irb->codegen->invalid_inst_src) + return target_value; + + AstNode *options_node = node->data.fn_call_expr.params.at(1); + IrInstSrc *options_value = ir_gen_node_extra(irb, options_node, + scope, LValNone, &result_loc_cast->base); + if (options_value == irb->codegen->invalid_inst_src) + return options_value; + + IrInstSrc *casted_options_value = ir_build_implicit_cast( + irb, scope, options_node, options_value, result_loc_cast); + + IrInstSrc *ir_export = ir_build_export(irb, scope, node, target_value, casted_options_value); + return ir_lval_wrap(irb, scope, ir_export, lval, result_loc); + } + case BuiltinFnIdExtern: + { + // Cast the options parameter to the options type + ZigType *options_type = get_builtin_type(irb->codegen, "ExternOptions"); + IrInstSrc *options_type_inst = ir_build_const_type(irb, scope, node, options_type); + ResultLocCast *result_loc_cast = ir_build_cast_result_loc(irb, options_type_inst, no_result_loc()); + + AstNode *type_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *type_value = ir_gen_node(irb, type_node, scope); + if (type_value == irb->codegen->invalid_inst_src) + return type_value; + + AstNode *options_node = node->data.fn_call_expr.params.at(1); + IrInstSrc *options_value = ir_gen_node_extra(irb, options_node, + scope, LValNone, &result_loc_cast->base); + if (options_value == irb->codegen->invalid_inst_src) + return options_value; + + IrInstSrc *casted_options_value = ir_build_implicit_cast( + irb, scope, options_node, options_value, result_loc_cast); + + IrInstSrc *ir_extern = ir_build_extern(irb, scope, node, type_value, casted_options_value); + return ir_lval_wrap(irb, scope, ir_extern, lval, result_loc); + } + case BuiltinFnIdErrorReturnTrace: + { + IrInstSrc *error_return_trace = ir_build_error_return_trace_src(irb, scope, node, + IrInstErrorReturnTraceNull); + return ir_lval_wrap(irb, scope, error_return_trace, lval, result_loc); + } + case BuiltinFnIdAtomicRmw: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) + return arg1_value; + + AstNode *arg2_node = node->data.fn_call_expr.params.at(2); + IrInstSrc *arg2_value = ir_gen_node(irb, arg2_node, scope); + if (arg2_value == irb->codegen->invalid_inst_src) + return arg2_value; + + AstNode *arg3_node = node->data.fn_call_expr.params.at(3); + IrInstSrc *arg3_value = ir_gen_node(irb, arg3_node, scope); + if (arg3_value == irb->codegen->invalid_inst_src) + return arg3_value; + + AstNode *arg4_node = node->data.fn_call_expr.params.at(4); + IrInstSrc *arg4_value = ir_gen_node(irb, arg4_node, scope); + if (arg4_value == irb->codegen->invalid_inst_src) + return arg4_value; + + IrInstSrc *inst = ir_build_atomic_rmw_src(irb, scope, node, + arg0_value, arg1_value, arg2_value, arg3_value, arg4_value); + return ir_lval_wrap(irb, scope, inst, lval, result_loc); + } + case BuiltinFnIdAtomicLoad: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) + return arg1_value; + + AstNode *arg2_node = node->data.fn_call_expr.params.at(2); + IrInstSrc *arg2_value = ir_gen_node(irb, arg2_node, scope); + if (arg2_value == irb->codegen->invalid_inst_src) + return arg2_value; + + IrInstSrc *inst = ir_build_atomic_load_src(irb, scope, node, arg0_value, arg1_value, arg2_value); + return ir_lval_wrap(irb, scope, inst, lval, result_loc); + } + case BuiltinFnIdAtomicStore: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) + return arg1_value; + + AstNode *arg2_node = node->data.fn_call_expr.params.at(2); + IrInstSrc *arg2_value = ir_gen_node(irb, arg2_node, scope); + if (arg2_value == irb->codegen->invalid_inst_src) + return arg2_value; + + AstNode *arg3_node = node->data.fn_call_expr.params.at(3); + IrInstSrc *arg3_value = ir_gen_node(irb, arg3_node, scope); + if (arg3_value == irb->codegen->invalid_inst_src) + return arg3_value; + + IrInstSrc *inst = ir_build_atomic_store_src(irb, scope, node, arg0_value, arg1_value, + arg2_value, arg3_value); + return ir_lval_wrap(irb, scope, inst, lval, result_loc); + } + case BuiltinFnIdIntToEnum: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) + return arg1_value; + + IrInstSrc *result = ir_build_int_to_enum_src(irb, scope, node, arg0_value, arg1_value); + return ir_lval_wrap(irb, scope, result, lval, result_loc); + } + case BuiltinFnIdEnumToInt: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + IrInstSrc *result = ir_build_enum_to_int(irb, scope, node, arg0_value); + return ir_lval_wrap(irb, scope, result, lval, result_loc); + } + case BuiltinFnIdCtz: + case BuiltinFnIdPopCount: + case BuiltinFnIdClz: + case BuiltinFnIdBswap: + case BuiltinFnIdBitReverse: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) + return arg1_value; + + IrInstSrc *result; + switch (builtin_fn->id) { + case BuiltinFnIdCtz: + result = ir_build_ctz(irb, scope, node, arg0_value, arg1_value); + break; + case BuiltinFnIdPopCount: + result = ir_build_pop_count(irb, scope, node, arg0_value, arg1_value); + break; + case BuiltinFnIdClz: + result = ir_build_clz(irb, scope, node, arg0_value, arg1_value); + break; + case BuiltinFnIdBswap: + result = ir_build_bswap(irb, scope, node, arg0_value, arg1_value); + break; + case BuiltinFnIdBitReverse: + result = ir_build_bit_reverse(irb, scope, node, arg0_value, arg1_value); + break; + default: + zig_unreachable(); + } + return ir_lval_wrap(irb, scope, result, lval, result_loc); + } + case BuiltinFnIdHasDecl: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) + return arg1_value; + + IrInstSrc *has_decl = ir_build_has_decl(irb, scope, node, arg0_value, arg1_value); + return ir_lval_wrap(irb, scope, has_decl, lval, result_loc); + } + case BuiltinFnIdUnionInit: + { + AstNode *union_type_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *union_type_inst = ir_gen_node(irb, union_type_node, scope); + if (union_type_inst == irb->codegen->invalid_inst_src) + return union_type_inst; + + AstNode *name_node = node->data.fn_call_expr.params.at(1); + IrInstSrc *name_inst = ir_gen_node(irb, name_node, scope); + if (name_inst == irb->codegen->invalid_inst_src) + return name_inst; + + AstNode *init_node = node->data.fn_call_expr.params.at(2); + + return ir_gen_union_init_expr(irb, scope, node, union_type_inst, name_inst, init_node, + lval, result_loc); + } + case BuiltinFnIdSrc: + { + IrInstSrc *src_inst = ir_build_src(irb, scope, node); + return ir_lval_wrap(irb, scope, src_inst, lval, result_loc); + } + } + zig_unreachable(); +} + +static ScopeNoSuspend *get_scope_nosuspend(Scope *scope) { + while (scope) { + if (scope->id == ScopeIdNoSuspend) + return (ScopeNoSuspend *)scope; + if (scope->id == ScopeIdFnDef) + return nullptr; + + scope = scope->parent; + } + return nullptr; +} + +static IrInstSrc *ir_gen_fn_call(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, + ResultLoc *result_loc) +{ + assert(node->type == NodeTypeFnCallExpr); + + if (node->data.fn_call_expr.modifier == CallModifierBuiltin) + return ir_gen_builtin_fn_call(irb, scope, node, lval, result_loc); + + bool is_nosuspend = get_scope_nosuspend(scope) != nullptr; + CallModifier modifier = node->data.fn_call_expr.modifier; + if (is_nosuspend && modifier != CallModifierAsync) { + modifier = CallModifierNoSuspend; + } + + AstNode *fn_ref_node = node->data.fn_call_expr.fn_ref_expr; + return ir_gen_fn_call_with_args(irb, scope, node, fn_ref_node, modifier, + nullptr, node->data.fn_call_expr.params.items, node->data.fn_call_expr.params.length, lval, result_loc); +} + +static IrInstSrc *ir_gen_if_bool_expr(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, + ResultLoc *result_loc) +{ + assert(node->type == NodeTypeIfBoolExpr); + + IrInstSrc *condition = ir_gen_node(irb, node->data.if_bool_expr.condition, scope); + if (condition == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + + IrInstSrc *is_comptime; + if (ir_should_inline(irb->exec, scope)) { + is_comptime = ir_build_const_bool(irb, scope, node, true); + } else { + is_comptime = ir_build_test_comptime(irb, scope, node, condition); + } + + AstNode *then_node = node->data.if_bool_expr.then_block; + AstNode *else_node = node->data.if_bool_expr.else_node; + + IrBasicBlockSrc *then_block = ir_create_basic_block(irb, scope, "Then"); + IrBasicBlockSrc *else_block = ir_create_basic_block(irb, scope, "Else"); + IrBasicBlockSrc *endif_block = ir_create_basic_block(irb, scope, "EndIf"); + + IrInstSrc *cond_br_inst = ir_build_cond_br(irb, scope, node, condition, + then_block, else_block, is_comptime); + ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, else_block, endif_block, + result_loc, is_comptime); + + ir_set_cursor_at_end_and_append_block(irb, then_block); + + Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime); + IrInstSrc *then_expr_result = ir_gen_node_extra(irb, then_node, subexpr_scope, lval, + &peer_parent->peers.at(0)->base); + if (then_expr_result == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + IrBasicBlockSrc *after_then_block = irb->current_basic_block; + if (!instr_is_unreachable(then_expr_result)) + ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime)); + + ir_set_cursor_at_end_and_append_block(irb, else_block); + IrInstSrc *else_expr_result; + if (else_node) { + else_expr_result = ir_gen_node_extra(irb, else_node, subexpr_scope, lval, &peer_parent->peers.at(1)->base); + if (else_expr_result == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + } else { + else_expr_result = ir_build_const_void(irb, scope, node); + ir_build_end_expr(irb, scope, node, else_expr_result, &peer_parent->peers.at(1)->base); + } + IrBasicBlockSrc *after_else_block = irb->current_basic_block; + if (!instr_is_unreachable(else_expr_result)) + ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime)); + + ir_set_cursor_at_end_and_append_block(irb, endif_block); + IrInstSrc **incoming_values = heap::c_allocator.allocate(2); + incoming_values[0] = then_expr_result; + incoming_values[1] = else_expr_result; + IrBasicBlockSrc **incoming_blocks = heap::c_allocator.allocate(2); + incoming_blocks[0] = after_then_block; + incoming_blocks[1] = after_else_block; + + IrInstSrc *phi = ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, peer_parent); + return ir_expr_wrap(irb, scope, phi, result_loc); +} + +static IrInstSrc *ir_gen_prefix_op_id_lval(IrBuilderSrc *irb, Scope *scope, AstNode *node, IrUnOp op_id, LVal lval) { + assert(node->type == NodeTypePrefixOpExpr); + AstNode *expr_node = node->data.prefix_op_expr.primary_expr; + + IrInstSrc *value = ir_gen_node_extra(irb, expr_node, scope, lval, nullptr); + if (value == irb->codegen->invalid_inst_src) + return value; + + return ir_build_un_op(irb, scope, node, op_id, value); +} + +static IrInstSrc *ir_gen_prefix_op_id(IrBuilderSrc *irb, Scope *scope, AstNode *node, IrUnOp op_id) { + return ir_gen_prefix_op_id_lval(irb, scope, node, op_id, LValNone); +} + +static IrInstSrc *ir_expr_wrap(IrBuilderSrc *irb, Scope *scope, IrInstSrc *inst, ResultLoc *result_loc) { + if (inst == irb->codegen->invalid_inst_src) return inst; + ir_build_end_expr(irb, scope, inst->base.source_node, inst, result_loc); + return inst; +} + +static IrInstSrc *ir_lval_wrap(IrBuilderSrc *irb, Scope *scope, IrInstSrc *value, LVal lval, + ResultLoc *result_loc) +{ + // This logic must be kept in sync with + // [STMT_EXPR_TEST_THING] <--- (search this token) + if (value == irb->codegen->invalid_inst_src || + instr_is_unreachable(value) || + value->base.source_node->type == NodeTypeDefer || + value->id == IrInstSrcIdDeclVar) + { + return value; + } + + assert(lval != LValAssign); + if (lval == LValPtr) { + // We needed a pointer to a value, but we got a value. So we create + // an instruction which just makes a pointer of it. + return ir_build_ref_src(irb, scope, value->base.source_node, value); + } else if (result_loc != nullptr) { + return ir_expr_wrap(irb, scope, value, result_loc); + } else { + return value; + } + +} + +static PtrLen star_token_to_ptr_len(TokenId token_id) { + switch (token_id) { + case TokenIdStar: + case TokenIdStarStar: + return PtrLenSingle; + case TokenIdLBracket: + return PtrLenUnknown; + case TokenIdIdentifier: + return PtrLenC; + default: + zig_unreachable(); + } +} + +static Error token_number_literal_u32(IrBuilderSrc *irb, AstNode *source_node, + RootStruct *root_struct, uint32_t *result, TokenIndex token) +{ + BigInt bigint; + token_number_literal_bigint(root_struct, &bigint, token); + + if (!bigint_fits_in_bits(&bigint, 32, false)) { + Buf *val_buf = buf_alloc(); + bigint_append_buf(val_buf, &bigint, 10); + exec_add_error_node(irb->codegen, irb->exec, source_node, + buf_sprintf("value %s too large for u32", buf_ptr(val_buf))); + bigint_deinit(&bigint); + return ErrorSemanticAnalyzeFail; + } + *result = bigint_as_u32(&bigint); + bigint_deinit(&bigint); + return ErrorNone; + +} + +static IrInstSrc *ir_gen_pointer_type(IrBuilderSrc *irb, Scope *scope, AstNode *node) { + Error err; + assert(node->type == NodeTypePointerType); + + RootStruct *root_struct = node->owner->data.structure.root_struct; + TokenId star_tok_id = root_struct->token_ids[node->data.pointer_type.star_token]; + PtrLen ptr_len = star_token_to_ptr_len(star_tok_id); + + bool is_const = node->data.pointer_type.is_const; + bool is_volatile = node->data.pointer_type.is_volatile; + bool is_allow_zero = node->data.pointer_type.allow_zero_token != 0; + AstNode *sentinel_expr = node->data.pointer_type.sentinel; + AstNode *expr_node = node->data.pointer_type.op_expr; + AstNode *align_expr = node->data.pointer_type.align_expr; + + IrInstSrc *sentinel; + if (sentinel_expr != nullptr) { + sentinel = ir_gen_node(irb, sentinel_expr, scope); + if (sentinel == irb->codegen->invalid_inst_src) + return sentinel; + } else { + sentinel = nullptr; + } + + IrInstSrc *align_value; + if (align_expr != nullptr) { + align_value = ir_gen_node(irb, align_expr, scope); + if (align_value == irb->codegen->invalid_inst_src) + return align_value; + } else { + align_value = nullptr; + } + + IrInstSrc *child_type = ir_gen_node(irb, expr_node, scope); + if (child_type == irb->codegen->invalid_inst_src) + return child_type; + + uint32_t bit_offset_start = 0; + if (node->data.pointer_type.bit_offset_start != 0) { + if ((err = token_number_literal_u32(irb, node, root_struct, &bit_offset_start, + node->data.pointer_type.bit_offset_start))) + { + return irb->codegen->invalid_inst_src; + } + } + + uint32_t host_int_bytes = 0; + if (node->data.pointer_type.host_int_bytes != 0) { + if ((err = token_number_literal_u32(irb, node, root_struct, &host_int_bytes, + node->data.pointer_type.host_int_bytes))) + { + return irb->codegen->invalid_inst_src; + } + } + + if (host_int_bytes != 0 && bit_offset_start >= host_int_bytes * 8) { + exec_add_error_node(irb->codegen, irb->exec, node, + buf_sprintf("bit offset starts after end of host integer")); + return irb->codegen->invalid_inst_src; + } + + return ir_build_ptr_type(irb, scope, node, child_type, is_const, is_volatile, + ptr_len, sentinel, align_value, bit_offset_start, host_int_bytes, is_allow_zero); +} + +static IrInstSrc *ir_gen_catch_unreachable(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + AstNode *expr_node, LVal lval, ResultLoc *result_loc) +{ + IrInstSrc *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr); + if (err_union_ptr == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + + IrInstSrc *payload_ptr = ir_build_unwrap_err_payload_src(irb, scope, source_node, err_union_ptr, true, false); + if (payload_ptr == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + + if (lval == LValPtr) + return payload_ptr; + + IrInstSrc *load_ptr = ir_build_load_ptr(irb, scope, source_node, payload_ptr); + return ir_expr_wrap(irb, scope, load_ptr, result_loc); +} + +static IrInstSrc *ir_gen_bool_not(IrBuilderSrc *irb, Scope *scope, AstNode *node) { + assert(node->type == NodeTypePrefixOpExpr); + AstNode *expr_node = node->data.prefix_op_expr.primary_expr; + + IrInstSrc *value = ir_gen_node(irb, expr_node, scope); + if (value == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + + return ir_build_bool_not(irb, scope, node, value); +} + +static IrInstSrc *ir_gen_prefix_op_expr(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, + ResultLoc *result_loc) +{ + assert(node->type == NodeTypePrefixOpExpr); + + PrefixOp prefix_op = node->data.prefix_op_expr.prefix_op; + + switch (prefix_op) { + case PrefixOpInvalid: + zig_unreachable(); + case PrefixOpBoolNot: + return ir_lval_wrap(irb, scope, ir_gen_bool_not(irb, scope, node), lval, result_loc); + case PrefixOpBinNot: + return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpBinNot), lval, result_loc); + case PrefixOpNegation: + return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegation), lval, result_loc); + case PrefixOpNegationWrap: + return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegationWrap), lval, result_loc); + case PrefixOpOptional: + return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpOptional), lval, result_loc); + case PrefixOpAddrOf: { + AstNode *expr_node = node->data.prefix_op_expr.primary_expr; + return ir_lval_wrap(irb, scope, ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr), lval, result_loc); + } + } + zig_unreachable(); +} + +static IrInstSrc *ir_gen_union_init_expr(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *union_type, IrInstSrc *field_name, AstNode *expr_node, + LVal lval, ResultLoc *parent_result_loc) +{ + IrInstSrc *container_ptr = ir_build_resolve_result(irb, scope, source_node, parent_result_loc, union_type); + IrInstSrc *field_ptr = ir_build_field_ptr_instruction(irb, scope, source_node, container_ptr, + field_name, true); + + ResultLocInstruction *result_loc_inst = heap::c_allocator.create(); + result_loc_inst->base.id = ResultLocIdInstruction; + result_loc_inst->base.source_instruction = field_ptr; + ir_ref_instruction(field_ptr, irb->current_basic_block); + ir_build_reset_result(irb, scope, expr_node, &result_loc_inst->base); + + IrInstSrc *expr_value = ir_gen_node_extra(irb, expr_node, scope, LValNone, + &result_loc_inst->base); + if (expr_value == irb->codegen->invalid_inst_src) + return expr_value; + + IrInstSrc *init_union = ir_build_union_init_named_field(irb, scope, source_node, union_type, + field_name, field_ptr, container_ptr); + + return ir_lval_wrap(irb, scope, init_union, lval, parent_result_loc); +} + +static IrInstSrc *ir_gen_container_init_expr(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, + ResultLoc *parent_result_loc) +{ + assert(node->type == NodeTypeContainerInitExpr); + + AstNodeContainerInitExpr *container_init_expr = &node->data.container_init_expr; + ContainerInitKind kind = container_init_expr->kind; + + ResultLocCast *result_loc_cast = nullptr; + ResultLoc *child_result_loc; + AstNode *init_array_type_source_node; + if (container_init_expr->type != nullptr) { + IrInstSrc *container_type; + if (container_init_expr->type->type == NodeTypeInferredArrayType) { + if (kind == ContainerInitKindStruct) { + add_node_error(irb->codegen, container_init_expr->type, + buf_sprintf("initializing array with struct syntax")); + return irb->codegen->invalid_inst_src; + } + IrInstSrc *sentinel; + if (container_init_expr->type->data.inferred_array_type.sentinel != nullptr) { + sentinel = ir_gen_node(irb, container_init_expr->type->data.inferred_array_type.sentinel, scope); + if (sentinel == irb->codegen->invalid_inst_src) + return sentinel; + } else { + sentinel = nullptr; + } + + IrInstSrc *elem_type = ir_gen_node(irb, + container_init_expr->type->data.inferred_array_type.child_type, scope); + if (elem_type == irb->codegen->invalid_inst_src) + return elem_type; + size_t item_count = container_init_expr->entries.length; + IrInstSrc *item_count_inst = ir_build_const_usize(irb, scope, node, item_count); + container_type = ir_build_array_type(irb, scope, node, item_count_inst, sentinel, elem_type); + } else { + container_type = ir_gen_node(irb, container_init_expr->type, scope); + if (container_type == irb->codegen->invalid_inst_src) + return container_type; + } + + result_loc_cast = ir_build_cast_result_loc(irb, container_type, parent_result_loc); + child_result_loc = &result_loc_cast->base; + init_array_type_source_node = container_type->base.source_node; + } else { + child_result_loc = parent_result_loc; + if (parent_result_loc->source_instruction != nullptr) { + init_array_type_source_node = parent_result_loc->source_instruction->base.source_node; + } else { + init_array_type_source_node = node; + } + } + + switch (kind) { + case ContainerInitKindStruct: { + IrInstSrc *container_ptr = ir_build_resolve_result(irb, scope, node, child_result_loc, + nullptr); + + size_t field_count = container_init_expr->entries.length; + IrInstSrcContainerInitFieldsField *fields = heap::c_allocator.allocate(field_count); + for (size_t i = 0; i < field_count; i += 1) { + AstNode *entry_node = container_init_expr->entries.at(i); + assert(entry_node->type == NodeTypeStructValueField); + + Buf *name = entry_node->data.struct_val_field.name; + AstNode *expr_node = entry_node->data.struct_val_field.expr; + + IrInstSrc *field_ptr = ir_build_field_ptr(irb, scope, entry_node, container_ptr, name, true); + ResultLocInstruction *result_loc_inst = heap::c_allocator.create(); + result_loc_inst->base.id = ResultLocIdInstruction; + result_loc_inst->base.source_instruction = field_ptr; + result_loc_inst->base.allow_write_through_const = true; + ir_ref_instruction(field_ptr, irb->current_basic_block); + ir_build_reset_result(irb, scope, expr_node, &result_loc_inst->base); + + IrInstSrc *expr_value = ir_gen_node_extra(irb, expr_node, scope, LValNone, + &result_loc_inst->base); + if (expr_value == irb->codegen->invalid_inst_src) + return expr_value; + + fields[i].name = name; + fields[i].source_node = entry_node; + fields[i].result_loc = field_ptr; + } + IrInstSrc *result = ir_build_container_init_fields(irb, scope, node, field_count, + fields, container_ptr); + + if (result_loc_cast != nullptr) { + result = ir_build_implicit_cast(irb, scope, node, result, result_loc_cast); + } + return ir_lval_wrap(irb, scope, result, lval, parent_result_loc); + } + case ContainerInitKindArray: { + size_t item_count = container_init_expr->entries.length; + + IrInstSrc *container_ptr = ir_build_resolve_result(irb, scope, node, child_result_loc, + nullptr); + + IrInstSrc **result_locs = heap::c_allocator.allocate(item_count); + for (size_t i = 0; i < item_count; i += 1) { + AstNode *expr_node = container_init_expr->entries.at(i); + + IrInstSrc *elem_index = ir_build_const_usize(irb, scope, expr_node, i); + IrInstSrc *elem_ptr = ir_build_elem_ptr(irb, scope, expr_node, container_ptr, + elem_index, false, PtrLenSingle, init_array_type_source_node); + ResultLocInstruction *result_loc_inst = heap::c_allocator.create(); + result_loc_inst->base.id = ResultLocIdInstruction; + result_loc_inst->base.source_instruction = elem_ptr; + result_loc_inst->base.allow_write_through_const = true; + ir_ref_instruction(elem_ptr, irb->current_basic_block); + ir_build_reset_result(irb, scope, expr_node, &result_loc_inst->base); + + IrInstSrc *expr_value = ir_gen_node_extra(irb, expr_node, scope, LValNone, + &result_loc_inst->base); + if (expr_value == irb->codegen->invalid_inst_src) + return expr_value; + + result_locs[i] = elem_ptr; + } + IrInstSrc *result = ir_build_container_init_list(irb, scope, node, item_count, + result_locs, container_ptr, init_array_type_source_node); + if (result_loc_cast != nullptr) { + result = ir_build_implicit_cast(irb, scope, node, result, result_loc_cast); + } + return ir_lval_wrap(irb, scope, result, lval, parent_result_loc); + } + } + zig_unreachable(); +} + +static ResultLocVar *ir_build_var_result_loc(IrBuilderSrc *irb, IrInstSrc *alloca, ZigVar *var) { + ResultLocVar *result_loc_var = heap::c_allocator.create(); + result_loc_var->base.id = ResultLocIdVar; + result_loc_var->base.source_instruction = alloca; + result_loc_var->base.allow_write_through_const = true; + result_loc_var->var = var; + + ir_build_reset_result(irb, alloca->base.scope, alloca->base.source_node, &result_loc_var->base); + + return result_loc_var; +} + +static ResultLocCast *ir_build_cast_result_loc(IrBuilderSrc *irb, IrInstSrc *dest_type, + ResultLoc *parent_result_loc) +{ + ResultLocCast *result_loc_cast = heap::c_allocator.create(); + result_loc_cast->base.id = ResultLocIdCast; + result_loc_cast->base.source_instruction = dest_type; + result_loc_cast->base.allow_write_through_const = parent_result_loc->allow_write_through_const; + ir_ref_instruction(dest_type, irb->current_basic_block); + result_loc_cast->parent = parent_result_loc; + + ir_build_reset_result(irb, dest_type->base.scope, dest_type->base.source_node, &result_loc_cast->base); + + return result_loc_cast; +} + +static void build_decl_var_and_init(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, ZigVar *var, + IrInstSrc *init, const char *name_hint, IrInstSrc *is_comptime) +{ + IrInstSrc *alloca = ir_build_alloca_src(irb, scope, source_node, nullptr, name_hint, is_comptime); + ResultLocVar *var_result_loc = ir_build_var_result_loc(irb, alloca, var); + ir_build_end_expr(irb, scope, source_node, init, &var_result_loc->base); + ir_build_var_decl_src(irb, scope, source_node, var, nullptr, alloca); +} + +static IrInstSrc *ir_gen_var_decl(IrBuilderSrc *irb, Scope *scope, AstNode *node) { + assert(node->type == NodeTypeVariableDeclaration); + + AstNodeVariableDeclaration *variable_declaration = &node->data.variable_declaration; + + if (buf_eql_str(variable_declaration->symbol, "_")) { + add_node_error(irb->codegen, node, buf_sprintf("`_` is not a declarable symbol")); + return irb->codegen->invalid_inst_src; + } + + // Used for the type expr and the align expr + Scope *comptime_scope = create_comptime_scope(irb->codegen, node, scope); + + IrInstSrc *type_instruction; + if (variable_declaration->type != nullptr) { + type_instruction = ir_gen_node(irb, variable_declaration->type, comptime_scope); + if (type_instruction == irb->codegen->invalid_inst_src) + return type_instruction; + } else { + type_instruction = nullptr; + } + + bool is_shadowable = false; + bool is_const = variable_declaration->is_const; + bool is_extern = variable_declaration->is_extern; + + bool is_comptime_scalar = ir_should_inline(irb->exec, scope) || variable_declaration->is_comptime; + IrInstSrc *is_comptime = ir_build_const_bool(irb, scope, node, is_comptime_scalar); + ZigVar *var = ir_create_var(irb, node, scope, variable_declaration->symbol, + is_const, is_const, is_shadowable, is_comptime); + // we detect IrInstSrcDeclVar in gen_block to make sure the next node + // is inside var->child_scope + + if (!is_extern && !variable_declaration->expr) { + var->var_type = irb->codegen->builtin_types.entry_invalid; + add_node_error(irb->codegen, node, buf_sprintf("variables must be initialized")); + return irb->codegen->invalid_inst_src; + } + + IrInstSrc *align_value = nullptr; + if (variable_declaration->align_expr != nullptr) { + align_value = ir_gen_node(irb, variable_declaration->align_expr, comptime_scope); + if (align_value == irb->codegen->invalid_inst_src) + return align_value; + } + + if (variable_declaration->section_expr != nullptr) { + add_node_error(irb->codegen, variable_declaration->section_expr, + buf_sprintf("cannot set section of local variable '%s'", buf_ptr(variable_declaration->symbol))); + } + + // Parser should ensure that this never happens + assert(variable_declaration->threadlocal_tok == 0); + + IrInstSrc *alloca = ir_build_alloca_src(irb, scope, node, align_value, + buf_ptr(variable_declaration->symbol), is_comptime); + + // Create a result location for the initialization expression. + ResultLocVar *result_loc_var = ir_build_var_result_loc(irb, alloca, var); + ResultLoc *init_result_loc; + ResultLocCast *result_loc_cast; + if (type_instruction != nullptr) { + result_loc_cast = ir_build_cast_result_loc(irb, type_instruction, &result_loc_var->base); + init_result_loc = &result_loc_cast->base; + } else { + result_loc_cast = nullptr; + init_result_loc = &result_loc_var->base; + } + + Scope *init_scope = is_comptime_scalar ? + create_comptime_scope(irb->codegen, variable_declaration->expr, scope) : scope; + + // Temporarily set the name of the IrExecutableSrc to the VariableDeclaration + // so that the struct or enum from the init expression inherits the name. + Buf *old_exec_name = irb->exec->name; + irb->exec->name = variable_declaration->symbol; + IrInstSrc *init_value = ir_gen_node_extra(irb, variable_declaration->expr, init_scope, + LValNone, init_result_loc); + irb->exec->name = old_exec_name; + + if (init_value == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + + if (result_loc_cast != nullptr) { + IrInstSrc *implicit_cast = ir_build_implicit_cast(irb, scope, init_value->base.source_node, + init_value, result_loc_cast); + ir_build_end_expr(irb, scope, node, implicit_cast, &result_loc_var->base); + } + + return ir_build_var_decl_src(irb, scope, node, var, align_value, alloca); +} + +static IrInstSrc *ir_gen_while_expr(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, + ResultLoc *result_loc) +{ + assert(node->type == NodeTypeWhileExpr); + + AstNode *continue_expr_node = node->data.while_expr.continue_expr; + AstNode *else_node = node->data.while_expr.else_node; + + IrBasicBlockSrc *cond_block = ir_create_basic_block(irb, scope, "WhileCond"); + IrBasicBlockSrc *body_block = ir_create_basic_block(irb, scope, "WhileBody"); + IrBasicBlockSrc *continue_block = continue_expr_node ? + ir_create_basic_block(irb, scope, "WhileContinue") : cond_block; + IrBasicBlockSrc *end_block = ir_create_basic_block(irb, scope, "WhileEnd"); + IrBasicBlockSrc *else_block = else_node ? + ir_create_basic_block(irb, scope, "WhileElse") : end_block; + + IrInstSrc *is_comptime = ir_build_const_bool(irb, scope, node, + ir_should_inline(irb->exec, scope) || node->data.while_expr.is_inline); + ir_build_br(irb, scope, node, cond_block, is_comptime); + + Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime); + Buf *var_symbol = node->data.while_expr.var_symbol; + Buf *err_symbol = node->data.while_expr.err_symbol; + if (err_symbol != nullptr) { + ir_set_cursor_at_end_and_append_block(irb, cond_block); + + Scope *payload_scope; + AstNode *symbol_node = node; // TODO make more accurate + ZigVar *payload_var; + if (var_symbol) { + // TODO make it an error to write to payload variable + payload_var = ir_create_var(irb, symbol_node, subexpr_scope, var_symbol, + true, false, false, is_comptime); + payload_scope = payload_var->child_scope; + } else { + payload_scope = subexpr_scope; + } + ScopeExpr *spill_scope = create_expr_scope(irb->codegen, node, payload_scope); + IrInstSrc *err_val_ptr = ir_gen_node_extra(irb, node->data.while_expr.condition, subexpr_scope, + LValPtr, nullptr); + if (err_val_ptr == irb->codegen->invalid_inst_src) + return err_val_ptr; + IrInstSrc *is_err = ir_build_test_err_src(irb, scope, node->data.while_expr.condition, err_val_ptr, + true, false); + IrBasicBlockSrc *after_cond_block = irb->current_basic_block; + IrInstSrc *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, scope, node)); + IrInstSrc *cond_br_inst; + if (!instr_is_unreachable(is_err)) { + cond_br_inst = ir_build_cond_br(irb, scope, node->data.while_expr.condition, is_err, + else_block, body_block, is_comptime); + cond_br_inst->is_gen = true; + } else { + // for the purposes of the source instruction to ir_build_result_peers + cond_br_inst = irb->current_basic_block->instruction_list.last(); + } + + ResultLocPeerParent *peer_parent = ir_build_result_peers(irb, cond_br_inst, end_block, result_loc, + is_comptime); + + ir_set_cursor_at_end_and_append_block(irb, body_block); + if (var_symbol) { + IrInstSrc *payload_ptr = ir_build_unwrap_err_payload_src(irb, &spill_scope->base, symbol_node, + err_val_ptr, false, false); + IrInstSrc *var_value = node->data.while_expr.var_is_ptr ? + payload_ptr : ir_build_load_ptr(irb, &spill_scope->base, symbol_node, payload_ptr); + build_decl_var_and_init(irb, payload_scope, symbol_node, payload_var, var_value, buf_ptr(var_symbol), is_comptime); + } + + ZigList incoming_values = {0}; + ZigList incoming_blocks = {0}; + + if (is_duplicate_label(irb->codegen, payload_scope, node, node->data.while_expr.name)) + return irb->codegen->invalid_inst_src; + + ScopeLoop *loop_scope = create_loop_scope(irb->codegen, node, payload_scope); + loop_scope->break_block = end_block; + loop_scope->continue_block = continue_block; + loop_scope->is_comptime = is_comptime; + loop_scope->incoming_blocks = &incoming_blocks; + loop_scope->incoming_values = &incoming_values; + loop_scope->lval = lval; + loop_scope->peer_parent = peer_parent; + loop_scope->spill_scope = spill_scope; + + // Note the body block of the loop is not the place that lval and result_loc are used - + // it's actually in break statements, handled similarly to return statements. + // That is why we set those values in loop_scope above and not in this ir_gen_node call. + IrInstSrc *body_result = ir_gen_node(irb, node->data.while_expr.body, &loop_scope->base); + if (body_result == irb->codegen->invalid_inst_src) + return body_result; + + if (loop_scope->name != nullptr && loop_scope->name_used == false) { + add_node_error(irb->codegen, node, buf_sprintf("unused while label")); + } + + if (!instr_is_unreachable(body_result)) { + ir_mark_gen(ir_build_check_statement_is_void(irb, payload_scope, node->data.while_expr.body, body_result)); + ir_mark_gen(ir_build_br(irb, payload_scope, node, continue_block, is_comptime)); + } + + if (continue_expr_node) { + ir_set_cursor_at_end_and_append_block(irb, continue_block); + IrInstSrc *expr_result = ir_gen_node(irb, continue_expr_node, payload_scope); + if (expr_result == irb->codegen->invalid_inst_src) + return expr_result; + if (!instr_is_unreachable(expr_result)) { + ir_mark_gen(ir_build_check_statement_is_void(irb, payload_scope, continue_expr_node, expr_result)); + ir_mark_gen(ir_build_br(irb, payload_scope, node, cond_block, is_comptime)); + } + } + + ir_set_cursor_at_end_and_append_block(irb, else_block); + assert(else_node != nullptr); + + // TODO make it an error to write to error variable + AstNode *err_symbol_node = else_node; // TODO make more accurate + ZigVar *err_var = ir_create_var(irb, err_symbol_node, scope, err_symbol, + true, false, false, is_comptime); + Scope *err_scope = err_var->child_scope; + IrInstSrc *err_ptr = ir_build_unwrap_err_code_src(irb, err_scope, err_symbol_node, err_val_ptr); + IrInstSrc *err_value = ir_build_load_ptr(irb, err_scope, err_symbol_node, err_ptr); + build_decl_var_and_init(irb, err_scope, err_symbol_node, err_var, err_value, buf_ptr(err_symbol), is_comptime); + + if (peer_parent->peers.length != 0) { + peer_parent->peers.last()->next_bb = else_block; + } + ResultLocPeer *peer_result = create_peer_result(peer_parent); + peer_parent->peers.append(peer_result); + IrInstSrc *else_result = ir_gen_node_extra(irb, else_node, err_scope, lval, &peer_result->base); + if (else_result == irb->codegen->invalid_inst_src) + return else_result; + if (!instr_is_unreachable(else_result)) + ir_mark_gen(ir_build_br(irb, scope, node, end_block, is_comptime)); + IrBasicBlockSrc *after_else_block = irb->current_basic_block; + ir_set_cursor_at_end_and_append_block(irb, end_block); + if (else_result) { + incoming_blocks.append(after_else_block); + incoming_values.append(else_result); + } else { + incoming_blocks.append(after_cond_block); + incoming_values.append(void_else_result); + } + if (peer_parent->peers.length != 0) { + peer_parent->peers.last()->next_bb = end_block; + } + + IrInstSrc *phi = ir_build_phi(irb, scope, node, incoming_blocks.length, + incoming_blocks.items, incoming_values.items, peer_parent); + return ir_expr_wrap(irb, scope, phi, result_loc); + } else if (var_symbol != nullptr) { + ir_set_cursor_at_end_and_append_block(irb, cond_block); + Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime); + // TODO make it an error to write to payload variable + AstNode *symbol_node = node; // TODO make more accurate + + ZigVar *payload_var = ir_create_var(irb, symbol_node, subexpr_scope, var_symbol, + true, false, false, is_comptime); + Scope *child_scope = payload_var->child_scope; + ScopeExpr *spill_scope = create_expr_scope(irb->codegen, node, child_scope); + IrInstSrc *maybe_val_ptr = ir_gen_node_extra(irb, node->data.while_expr.condition, subexpr_scope, + LValPtr, nullptr); + if (maybe_val_ptr == irb->codegen->invalid_inst_src) + return maybe_val_ptr; + IrInstSrc *maybe_val = ir_build_load_ptr(irb, scope, node->data.while_expr.condition, maybe_val_ptr); + IrInstSrc *is_non_null = ir_build_test_non_null_src(irb, scope, node->data.while_expr.condition, maybe_val); + IrBasicBlockSrc *after_cond_block = irb->current_basic_block; + IrInstSrc *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, scope, node)); + IrInstSrc *cond_br_inst; + if (!instr_is_unreachable(is_non_null)) { + cond_br_inst = ir_build_cond_br(irb, scope, node->data.while_expr.condition, is_non_null, + body_block, else_block, is_comptime); + cond_br_inst->is_gen = true; + } else { + // for the purposes of the source instruction to ir_build_result_peers + cond_br_inst = irb->current_basic_block->instruction_list.last(); + } + + ResultLocPeerParent *peer_parent = ir_build_result_peers(irb, cond_br_inst, end_block, result_loc, + is_comptime); + + ir_set_cursor_at_end_and_append_block(irb, body_block); + IrInstSrc *payload_ptr = ir_build_optional_unwrap_ptr(irb, &spill_scope->base, symbol_node, maybe_val_ptr, false); + IrInstSrc *var_value = node->data.while_expr.var_is_ptr ? + payload_ptr : ir_build_load_ptr(irb, &spill_scope->base, symbol_node, payload_ptr); + build_decl_var_and_init(irb, child_scope, symbol_node, payload_var, var_value, buf_ptr(var_symbol), is_comptime); + + ZigList incoming_values = {0}; + ZigList incoming_blocks = {0}; + + if (is_duplicate_label(irb->codegen, child_scope, node, node->data.while_expr.name)) + return irb->codegen->invalid_inst_src; + + ScopeLoop *loop_scope = create_loop_scope(irb->codegen, node, child_scope); + loop_scope->break_block = end_block; + loop_scope->continue_block = continue_block; + loop_scope->is_comptime = is_comptime; + loop_scope->incoming_blocks = &incoming_blocks; + loop_scope->incoming_values = &incoming_values; + loop_scope->lval = lval; + loop_scope->peer_parent = peer_parent; + loop_scope->spill_scope = spill_scope; + + // Note the body block of the loop is not the place that lval and result_loc are used - + // it's actually in break statements, handled similarly to return statements. + // That is why we set those values in loop_scope above and not in this ir_gen_node call. + IrInstSrc *body_result = ir_gen_node(irb, node->data.while_expr.body, &loop_scope->base); + if (body_result == irb->codegen->invalid_inst_src) + return body_result; + + if (loop_scope->name != nullptr && loop_scope->name_used == false) { + add_node_error(irb->codegen, node, buf_sprintf("unused while label")); + } + + if (!instr_is_unreachable(body_result)) { + ir_mark_gen(ir_build_check_statement_is_void(irb, child_scope, node->data.while_expr.body, body_result)); + ir_mark_gen(ir_build_br(irb, child_scope, node, continue_block, is_comptime)); + } + + if (continue_expr_node) { + ir_set_cursor_at_end_and_append_block(irb, continue_block); + IrInstSrc *expr_result = ir_gen_node(irb, continue_expr_node, child_scope); + if (expr_result == irb->codegen->invalid_inst_src) + return expr_result; + if (!instr_is_unreachable(expr_result)) { + ir_mark_gen(ir_build_check_statement_is_void(irb, child_scope, continue_expr_node, expr_result)); + ir_mark_gen(ir_build_br(irb, child_scope, node, cond_block, is_comptime)); + } + } + + IrInstSrc *else_result = nullptr; + if (else_node) { + ir_set_cursor_at_end_and_append_block(irb, else_block); + + if (peer_parent->peers.length != 0) { + peer_parent->peers.last()->next_bb = else_block; + } + ResultLocPeer *peer_result = create_peer_result(peer_parent); + peer_parent->peers.append(peer_result); + else_result = ir_gen_node_extra(irb, else_node, scope, lval, &peer_result->base); + if (else_result == irb->codegen->invalid_inst_src) + return else_result; + if (!instr_is_unreachable(else_result)) + ir_mark_gen(ir_build_br(irb, scope, node, end_block, is_comptime)); + } + IrBasicBlockSrc *after_else_block = irb->current_basic_block; + ir_set_cursor_at_end_and_append_block(irb, end_block); + if (else_result) { + incoming_blocks.append(after_else_block); + incoming_values.append(else_result); + } else { + incoming_blocks.append(after_cond_block); + incoming_values.append(void_else_result); + } + if (peer_parent->peers.length != 0) { + peer_parent->peers.last()->next_bb = end_block; + } + + IrInstSrc *phi = ir_build_phi(irb, scope, node, incoming_blocks.length, + incoming_blocks.items, incoming_values.items, peer_parent); + return ir_expr_wrap(irb, scope, phi, result_loc); + } else { + ir_set_cursor_at_end_and_append_block(irb, cond_block); + IrInstSrc *cond_val = ir_gen_node(irb, node->data.while_expr.condition, scope); + if (cond_val == irb->codegen->invalid_inst_src) + return cond_val; + IrBasicBlockSrc *after_cond_block = irb->current_basic_block; + IrInstSrc *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, scope, node)); + IrInstSrc *cond_br_inst; + if (!instr_is_unreachable(cond_val)) { + cond_br_inst = ir_build_cond_br(irb, scope, node->data.while_expr.condition, cond_val, + body_block, else_block, is_comptime); + cond_br_inst->is_gen = true; + } else { + // for the purposes of the source instruction to ir_build_result_peers + cond_br_inst = irb->current_basic_block->instruction_list.last(); + } + + ResultLocPeerParent *peer_parent = ir_build_result_peers(irb, cond_br_inst, end_block, result_loc, + is_comptime); + ir_set_cursor_at_end_and_append_block(irb, body_block); + + ZigList incoming_values = {0}; + ZigList incoming_blocks = {0}; + + Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime); + + if (is_duplicate_label(irb->codegen, subexpr_scope, node, node->data.while_expr.name)) + return irb->codegen->invalid_inst_src; + + ScopeLoop *loop_scope = create_loop_scope(irb->codegen, node, subexpr_scope); + loop_scope->break_block = end_block; + loop_scope->continue_block = continue_block; + loop_scope->is_comptime = is_comptime; + loop_scope->incoming_blocks = &incoming_blocks; + loop_scope->incoming_values = &incoming_values; + loop_scope->lval = lval; + loop_scope->peer_parent = peer_parent; + + // Note the body block of the loop is not the place that lval and result_loc are used - + // it's actually in break statements, handled similarly to return statements. + // That is why we set those values in loop_scope above and not in this ir_gen_node call. + IrInstSrc *body_result = ir_gen_node(irb, node->data.while_expr.body, &loop_scope->base); + if (body_result == irb->codegen->invalid_inst_src) + return body_result; + + if (loop_scope->name != nullptr && loop_scope->name_used == false) { + add_node_error(irb->codegen, node, buf_sprintf("unused while label")); + } + + if (!instr_is_unreachable(body_result)) { + ir_mark_gen(ir_build_check_statement_is_void(irb, scope, node->data.while_expr.body, body_result)); + ir_mark_gen(ir_build_br(irb, scope, node, continue_block, is_comptime)); + } + + if (continue_expr_node) { + ir_set_cursor_at_end_and_append_block(irb, continue_block); + IrInstSrc *expr_result = ir_gen_node(irb, continue_expr_node, subexpr_scope); + if (expr_result == irb->codegen->invalid_inst_src) + return expr_result; + if (!instr_is_unreachable(expr_result)) { + ir_mark_gen(ir_build_check_statement_is_void(irb, scope, continue_expr_node, expr_result)); + ir_mark_gen(ir_build_br(irb, scope, node, cond_block, is_comptime)); + } + } + + IrInstSrc *else_result = nullptr; + if (else_node) { + ir_set_cursor_at_end_and_append_block(irb, else_block); + + if (peer_parent->peers.length != 0) { + peer_parent->peers.last()->next_bb = else_block; + } + ResultLocPeer *peer_result = create_peer_result(peer_parent); + peer_parent->peers.append(peer_result); + + else_result = ir_gen_node_extra(irb, else_node, subexpr_scope, lval, &peer_result->base); + if (else_result == irb->codegen->invalid_inst_src) + return else_result; + if (!instr_is_unreachable(else_result)) + ir_mark_gen(ir_build_br(irb, scope, node, end_block, is_comptime)); + } + IrBasicBlockSrc *after_else_block = irb->current_basic_block; + ir_set_cursor_at_end_and_append_block(irb, end_block); + if (else_result) { + incoming_blocks.append(after_else_block); + incoming_values.append(else_result); + } else { + incoming_blocks.append(after_cond_block); + incoming_values.append(void_else_result); + } + if (peer_parent->peers.length != 0) { + peer_parent->peers.last()->next_bb = end_block; + } + + IrInstSrc *phi = ir_build_phi(irb, scope, node, incoming_blocks.length, + incoming_blocks.items, incoming_values.items, peer_parent); + return ir_expr_wrap(irb, scope, phi, result_loc); + } +} + +static IrInstSrc *ir_gen_for_expr(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node, LVal lval, + ResultLoc *result_loc) +{ + assert(node->type == NodeTypeForExpr); + + AstNode *array_node = node->data.for_expr.array_expr; + AstNode *elem_node = node->data.for_expr.elem_node; + AstNode *index_node = node->data.for_expr.index_node; + AstNode *body_node = node->data.for_expr.body; + AstNode *else_node = node->data.for_expr.else_node; + + if (!elem_node) { + add_node_error(irb->codegen, node, buf_sprintf("for loop expression missing element parameter")); + return irb->codegen->invalid_inst_src; + } + assert(elem_node->type == NodeTypeIdentifier); + + ScopeExpr *spill_scope = create_expr_scope(irb->codegen, node, parent_scope); + + IrInstSrc *array_val_ptr = ir_gen_node_extra(irb, array_node, &spill_scope->base, LValPtr, nullptr); + if (array_val_ptr == irb->codegen->invalid_inst_src) + return array_val_ptr; + + IrInstSrc *is_comptime = ir_build_const_bool(irb, parent_scope, node, + ir_should_inline(irb->exec, parent_scope) || node->data.for_expr.is_inline); + + AstNode *index_var_source_node; + ZigVar *index_var; + const char *index_var_name; + if (index_node) { + index_var_source_node = index_node; + Buf *index_var_name_buf = node_identifier_buf(index_node); + index_var = ir_create_var(irb, index_node, parent_scope, index_var_name_buf, true, false, false, is_comptime); + index_var_name = buf_ptr(index_var_name_buf); + } else { + index_var_source_node = node; + index_var = ir_create_var(irb, node, parent_scope, nullptr, true, false, true, is_comptime); + index_var_name = "i"; + } + + IrInstSrc *zero = ir_build_const_usize(irb, parent_scope, node, 0); + build_decl_var_and_init(irb, parent_scope, index_var_source_node, index_var, zero, index_var_name, is_comptime); + parent_scope = index_var->child_scope; + + IrInstSrc *one = ir_build_const_usize(irb, parent_scope, node, 1); + IrInstSrc *index_ptr = ir_build_var_ptr(irb, parent_scope, node, index_var); + + + IrBasicBlockSrc *cond_block = ir_create_basic_block(irb, parent_scope, "ForCond"); + IrBasicBlockSrc *body_block = ir_create_basic_block(irb, parent_scope, "ForBody"); + IrBasicBlockSrc *end_block = ir_create_basic_block(irb, parent_scope, "ForEnd"); + IrBasicBlockSrc *else_block = else_node ? ir_create_basic_block(irb, parent_scope, "ForElse") : end_block; + IrBasicBlockSrc *continue_block = ir_create_basic_block(irb, parent_scope, "ForContinue"); + + Buf *len_field_name = buf_create_from_str("len"); + IrInstSrc *len_ref = ir_build_field_ptr(irb, parent_scope, node, array_val_ptr, len_field_name, false); + IrInstSrc *len_val = ir_build_load_ptr(irb, &spill_scope->base, node, len_ref); + ir_build_br(irb, parent_scope, node, cond_block, is_comptime); + + ir_set_cursor_at_end_and_append_block(irb, cond_block); + IrInstSrc *index_val = ir_build_load_ptr(irb, &spill_scope->base, node, index_ptr); + IrInstSrc *cond = ir_build_bin_op(irb, parent_scope, node, IrBinOpCmpLessThan, index_val, len_val, false); + IrBasicBlockSrc *after_cond_block = irb->current_basic_block; + IrInstSrc *void_else_value = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, parent_scope, node)); + IrInstSrc *cond_br_inst = ir_mark_gen(ir_build_cond_br(irb, parent_scope, node, cond, + body_block, else_block, is_comptime)); + + ResultLocPeerParent *peer_parent = ir_build_result_peers(irb, cond_br_inst, end_block, result_loc, is_comptime); + + ir_set_cursor_at_end_and_append_block(irb, body_block); + IrInstSrc *elem_ptr = ir_build_elem_ptr(irb, &spill_scope->base, node, array_val_ptr, index_val, + false, PtrLenSingle, nullptr); + // TODO make it an error to write to element variable or i variable. + Buf *elem_var_name = node_identifier_buf(elem_node); + ZigVar *elem_var = ir_create_var(irb, elem_node, parent_scope, elem_var_name, true, false, false, is_comptime); + Scope *child_scope = elem_var->child_scope; + + IrInstSrc *elem_value = node->data.for_expr.elem_is_ptr ? + elem_ptr : ir_build_load_ptr(irb, &spill_scope->base, elem_node, elem_ptr); + build_decl_var_and_init(irb, parent_scope, elem_node, elem_var, elem_value, buf_ptr(elem_var_name), is_comptime); + + if (is_duplicate_label(irb->codegen, child_scope, node, node->data.for_expr.name)) + return irb->codegen->invalid_inst_src; + + ZigList incoming_values = {0}; + ZigList incoming_blocks = {0}; + ScopeLoop *loop_scope = create_loop_scope(irb->codegen, node, child_scope); + loop_scope->break_block = end_block; + loop_scope->continue_block = continue_block; + loop_scope->is_comptime = is_comptime; + loop_scope->incoming_blocks = &incoming_blocks; + loop_scope->incoming_values = &incoming_values; + loop_scope->lval = LValNone; + loop_scope->peer_parent = peer_parent; + loop_scope->spill_scope = spill_scope; + + // Note the body block of the loop is not the place that lval and result_loc are used - + // it's actually in break statements, handled similarly to return statements. + // That is why we set those values in loop_scope above and not in this ir_gen_node call. + IrInstSrc *body_result = ir_gen_node(irb, body_node, &loop_scope->base); + if (body_result == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + + if (loop_scope->name != nullptr && loop_scope->name_used == false) { + add_node_error(irb->codegen, node, buf_sprintf("unused for label")); + } + + if (!instr_is_unreachable(body_result)) { + ir_mark_gen(ir_build_check_statement_is_void(irb, child_scope, node->data.for_expr.body, body_result)); + ir_mark_gen(ir_build_br(irb, child_scope, node, continue_block, is_comptime)); + } + + ir_set_cursor_at_end_and_append_block(irb, continue_block); + IrInstSrc *new_index_val = ir_build_bin_op(irb, child_scope, node, IrBinOpAdd, index_val, one, false); + ir_build_store_ptr(irb, child_scope, node, index_ptr, new_index_val)->allow_write_through_const = true; + ir_build_br(irb, child_scope, node, cond_block, is_comptime); + + IrInstSrc *else_result = nullptr; + if (else_node) { + ir_set_cursor_at_end_and_append_block(irb, else_block); + + if (peer_parent->peers.length != 0) { + peer_parent->peers.last()->next_bb = else_block; + } + ResultLocPeer *peer_result = create_peer_result(peer_parent); + peer_parent->peers.append(peer_result); + else_result = ir_gen_node_extra(irb, else_node, parent_scope, LValNone, &peer_result->base); + if (else_result == irb->codegen->invalid_inst_src) + return else_result; + if (!instr_is_unreachable(else_result)) + ir_mark_gen(ir_build_br(irb, parent_scope, node, end_block, is_comptime)); + } + IrBasicBlockSrc *after_else_block = irb->current_basic_block; + ir_set_cursor_at_end_and_append_block(irb, end_block); + + if (else_result) { + incoming_blocks.append(after_else_block); + incoming_values.append(else_result); + } else { + incoming_blocks.append(after_cond_block); + incoming_values.append(void_else_value); + } + if (peer_parent->peers.length != 0) { + peer_parent->peers.last()->next_bb = end_block; + } + + IrInstSrc *phi = ir_build_phi(irb, parent_scope, node, incoming_blocks.length, + incoming_blocks.items, incoming_values.items, peer_parent); + return ir_lval_wrap(irb, parent_scope, phi, lval, result_loc); +} + +static IrInstSrc *ir_gen_bool_literal(IrBuilderSrc *irb, Scope *scope, AstNode *node) { + assert(node->type == NodeTypeBoolLiteral); + return ir_build_const_bool(irb, scope, node, node->data.bool_literal.value); +} + +static IrInstSrc *ir_gen_enum_literal(IrBuilderSrc *irb, Scope *scope, AstNode *node) { + assert(node->type == NodeTypeEnumLiteral); + RootStruct *root_struct = node->owner->data.structure.root_struct; + Buf *name = token_identifier_buf(root_struct, node->main_token + 1); + return ir_build_const_enum_literal(irb, scope, node, name); +} + +static IrInstSrc *ir_gen_string_literal(IrBuilderSrc *irb, Scope *scope, AstNode *node) { + Error err; + assert(node->type == NodeTypeStringLiteral); + + RootStruct *root_struct = node->owner->data.structure.root_struct; + const char *source = buf_ptr(root_struct->source_code); + + TokenId *token_ids = root_struct->token_ids; + + Buf *str = buf_alloc(); + if (token_ids[node->main_token] == TokenIdStringLiteral) { + size_t byte_offset = root_struct->token_locs[node->main_token].offset; + size_t bad_index; + if ((err = source_string_literal_buf(source + byte_offset, str, &bad_index))) { + add_token_error_offset(irb->codegen, node->owner, node->main_token, + buf_create_from_str("invalid string literal character"), bad_index); + } + src_assert(source[byte_offset] == '"', node); + byte_offset += 1; + } else if (token_ids[node->main_token] == TokenIdMultilineStringLiteralLine) { + TokenIndex tok_index = node->main_token; + bool first = true; + for (;token_ids[tok_index] == TokenIdMultilineStringLiteralLine; tok_index += 1) { + size_t byte_offset = root_struct->token_locs[tok_index].offset; + size_t end = byte_offset; + while (source[end] != 0 && source[end] != '\n') { + end += 1; + } + if (!first) { + buf_append_char(str, '\n'); + } else { + first = false; + } + buf_append_mem(str, source + byte_offset + 2, end - byte_offset - 2); + } + } else { + zig_unreachable(); + } + return ir_build_const_str_lit(irb, scope, node, str); +} + +static IrInstSrc *ir_gen_array_type(IrBuilderSrc *irb, Scope *scope, AstNode *node) { + assert(node->type == NodeTypeArrayType); + + AstNode *size_node = node->data.array_type.size; + AstNode *child_type_node = node->data.array_type.child_type; + bool is_const = node->data.array_type.is_const; + bool is_volatile = node->data.array_type.is_volatile; + bool is_allow_zero = node->data.array_type.allow_zero_token != 0; + AstNode *sentinel_expr = node->data.array_type.sentinel; + AstNode *align_expr = node->data.array_type.align_expr; + + Scope *comptime_scope = create_comptime_scope(irb->codegen, node, scope); + + IrInstSrc *sentinel; + if (sentinel_expr != nullptr) { + sentinel = ir_gen_node(irb, sentinel_expr, comptime_scope); + if (sentinel == irb->codegen->invalid_inst_src) + return sentinel; + } else { + sentinel = nullptr; + } + + if (size_node) { + if (is_const) { + add_node_error(irb->codegen, node, buf_create_from_str("const qualifier invalid on array type")); + return irb->codegen->invalid_inst_src; + } + if (is_volatile) { + add_node_error(irb->codegen, node, buf_create_from_str("volatile qualifier invalid on array type")); + return irb->codegen->invalid_inst_src; + } + if (is_allow_zero) { + add_node_error(irb->codegen, node, buf_create_from_str("allowzero qualifier invalid on array type")); + return irb->codegen->invalid_inst_src; + } + if (align_expr != nullptr) { + add_node_error(irb->codegen, node, buf_create_from_str("align qualifier invalid on array type")); + return irb->codegen->invalid_inst_src; + } + + IrInstSrc *size_value = ir_gen_node(irb, size_node, comptime_scope); + if (size_value == irb->codegen->invalid_inst_src) + return size_value; + + IrInstSrc *child_type = ir_gen_node(irb, child_type_node, comptime_scope); + if (child_type == irb->codegen->invalid_inst_src) + return child_type; + + return ir_build_array_type(irb, scope, node, size_value, sentinel, child_type); + } else { + IrInstSrc *align_value; + if (align_expr != nullptr) { + align_value = ir_gen_node(irb, align_expr, comptime_scope); + if (align_value == irb->codegen->invalid_inst_src) + return align_value; + } else { + align_value = nullptr; + } + + IrInstSrc *child_type = ir_gen_node(irb, child_type_node, comptime_scope); + if (child_type == irb->codegen->invalid_inst_src) + return child_type; + + return ir_build_slice_type(irb, scope, node, child_type, is_const, is_volatile, sentinel, + align_value, is_allow_zero); + } +} + +static IrInstSrc *ir_gen_anyframe_type(IrBuilderSrc *irb, Scope *scope, AstNode *node) { + assert(node->type == NodeTypeAnyFrameType); + + AstNode *payload_type_node = node->data.anyframe_type.payload_type; + IrInstSrc *payload_type_value = nullptr; + + if (payload_type_node != nullptr) { + payload_type_value = ir_gen_node(irb, payload_type_node, scope); + if (payload_type_value == irb->codegen->invalid_inst_src) + return payload_type_value; + + } + + return ir_build_anyframe_type(irb, scope, node, payload_type_value); +} + +static IrInstSrc *ir_gen_undefined_literal(IrBuilderSrc *irb, Scope *scope, AstNode *node) { + assert(node->type == NodeTypeUndefinedLiteral); + return ir_build_const_undefined(irb, scope, node); +} + +static IrInstSrc *ir_gen_asm_expr(IrBuilderSrc *irb, Scope *scope, AstNode *node) { + assert(node->type == NodeTypeAsmExpr); + AstNodeAsmExpr *asm_expr = &node->data.asm_expr; + + IrInstSrc *asm_template = ir_gen_node(irb, asm_expr->asm_template, scope); + if (asm_template == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + + bool is_volatile = asm_expr->volatile_token != 0; + bool in_fn_scope = (scope_fn_entry(scope) != nullptr); + + if (!in_fn_scope) { + if (is_volatile) { + add_token_error(irb->codegen, node->owner, asm_expr->volatile_token, + buf_sprintf("volatile is meaningless on global assembly")); + return irb->codegen->invalid_inst_src; + } + + if (asm_expr->output_list.length != 0 || asm_expr->input_list.length != 0 || + asm_expr->clobber_list.length != 0) + { + add_node_error(irb->codegen, node, + buf_sprintf("global assembly cannot have inputs, outputs, or clobbers")); + return irb->codegen->invalid_inst_src; + } + + return ir_build_asm_src(irb, scope, node, asm_template, nullptr, nullptr, + nullptr, 0, is_volatile, true); + } + + IrInstSrc **input_list = heap::c_allocator.allocate(asm_expr->input_list.length); + IrInstSrc **output_types = heap::c_allocator.allocate(asm_expr->output_list.length); + ZigVar **output_vars = heap::c_allocator.allocate(asm_expr->output_list.length); + size_t return_count = 0; + if (!is_volatile && asm_expr->output_list.length == 0) { + add_node_error(irb->codegen, node, + buf_sprintf("assembly expression with no output must be marked volatile")); + return irb->codegen->invalid_inst_src; + } + for (size_t i = 0; i < asm_expr->output_list.length; i += 1) { + AsmOutput *asm_output = asm_expr->output_list.at(i); + if (asm_output->return_type) { + return_count += 1; + + IrInstSrc *return_type = ir_gen_node(irb, asm_output->return_type, scope); + if (return_type == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + if (return_count > 1) { + add_node_error(irb->codegen, node, + buf_sprintf("inline assembly allows up to one output value")); + return irb->codegen->invalid_inst_src; + } + output_types[i] = return_type; + } else { + Buf *variable_name = asm_output->variable_name; + // TODO there is some duplication here with ir_gen_symbol. I need to do a full audit of how + // inline assembly works. https://github.com/ziglang/zig/issues/215 + ZigVar *var = find_variable(irb->codegen, scope, variable_name, nullptr); + if (var) { + output_vars[i] = var; + } else { + add_node_error(irb->codegen, node, + buf_sprintf("use of undeclared identifier '%s'", buf_ptr(variable_name))); + return irb->codegen->invalid_inst_src; + } + } + + const char modifier = *buf_ptr(asm_output->constraint); + if (modifier != '=') { + add_node_error(irb->codegen, node, + buf_sprintf("invalid modifier starting output constraint for '%s': '%c', only '=' is supported." + " Compiler TODO: see https://github.com/ziglang/zig/issues/215", + buf_ptr(asm_output->asm_symbolic_name), modifier)); + return irb->codegen->invalid_inst_src; + } + } + for (size_t i = 0; i < asm_expr->input_list.length; i += 1) { + AsmInput *asm_input = asm_expr->input_list.at(i); + IrInstSrc *input_value = ir_gen_node(irb, asm_input->expr, scope); + if (input_value == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + + input_list[i] = input_value; + } + + return ir_build_asm_src(irb, scope, node, asm_template, input_list, output_types, + output_vars, return_count, is_volatile, false); +} + +static IrInstSrc *ir_gen_if_optional_expr(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, + ResultLoc *result_loc) +{ + assert(node->type == NodeTypeIfOptional); + + Buf *var_symbol = node->data.test_expr.var_symbol; + AstNode *expr_node = node->data.test_expr.target_node; + AstNode *then_node = node->data.test_expr.then_node; + AstNode *else_node = node->data.test_expr.else_node; + bool var_is_ptr = node->data.test_expr.var_is_ptr; + + ScopeExpr *spill_scope = create_expr_scope(irb->codegen, expr_node, scope); + spill_scope->spill_harder = true; + + IrInstSrc *maybe_val_ptr = ir_gen_node_extra(irb, expr_node, &spill_scope->base, LValPtr, nullptr); + if (maybe_val_ptr == irb->codegen->invalid_inst_src) + return maybe_val_ptr; + + IrInstSrc *maybe_val = ir_build_load_ptr(irb, scope, node, maybe_val_ptr); + IrInstSrc *is_non_null = ir_build_test_non_null_src(irb, scope, node, maybe_val); + + IrBasicBlockSrc *then_block = ir_create_basic_block(irb, scope, "OptionalThen"); + IrBasicBlockSrc *else_block = ir_create_basic_block(irb, scope, "OptionalElse"); + IrBasicBlockSrc *endif_block = ir_create_basic_block(irb, scope, "OptionalEndIf"); + + IrInstSrc *is_comptime; + if (ir_should_inline(irb->exec, scope)) { + is_comptime = ir_build_const_bool(irb, scope, node, true); + } else { + is_comptime = ir_build_test_comptime(irb, scope, node, is_non_null); + } + IrInstSrc *cond_br_inst = ir_build_cond_br(irb, scope, node, is_non_null, + then_block, else_block, is_comptime); + + ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, else_block, endif_block, + result_loc, is_comptime); + + ir_set_cursor_at_end_and_append_block(irb, then_block); + + Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, &spill_scope->base, is_comptime); + Scope *var_scope; + if (var_symbol) { + bool is_shadowable = false; + bool is_const = true; + ZigVar *var = ir_create_var(irb, node, subexpr_scope, + var_symbol, is_const, is_const, is_shadowable, is_comptime); + + IrInstSrc *payload_ptr = ir_build_optional_unwrap_ptr(irb, subexpr_scope, node, maybe_val_ptr, false); + IrInstSrc *var_value = var_is_ptr ? + payload_ptr : ir_build_load_ptr(irb, &spill_scope->base, node, payload_ptr); + build_decl_var_and_init(irb, subexpr_scope, node, var, var_value, buf_ptr(var_symbol), is_comptime); + var_scope = var->child_scope; + } else { + var_scope = subexpr_scope; + } + IrInstSrc *then_expr_result = ir_gen_node_extra(irb, then_node, var_scope, lval, + &peer_parent->peers.at(0)->base); + if (then_expr_result == irb->codegen->invalid_inst_src) + return then_expr_result; + IrBasicBlockSrc *after_then_block = irb->current_basic_block; + if (!instr_is_unreachable(then_expr_result)) + ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime)); + + ir_set_cursor_at_end_and_append_block(irb, else_block); + IrInstSrc *else_expr_result; + if (else_node) { + else_expr_result = ir_gen_node_extra(irb, else_node, subexpr_scope, lval, &peer_parent->peers.at(1)->base); + if (else_expr_result == irb->codegen->invalid_inst_src) + return else_expr_result; + } else { + else_expr_result = ir_build_const_void(irb, scope, node); + ir_build_end_expr(irb, scope, node, else_expr_result, &peer_parent->peers.at(1)->base); + } + IrBasicBlockSrc *after_else_block = irb->current_basic_block; + if (!instr_is_unreachable(else_expr_result)) + ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime)); + + ir_set_cursor_at_end_and_append_block(irb, endif_block); + IrInstSrc **incoming_values = heap::c_allocator.allocate(2); + incoming_values[0] = then_expr_result; + incoming_values[1] = else_expr_result; + IrBasicBlockSrc **incoming_blocks = heap::c_allocator.allocate(2); + incoming_blocks[0] = after_then_block; + incoming_blocks[1] = after_else_block; + + IrInstSrc *phi = ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, peer_parent); + return ir_expr_wrap(irb, scope, phi, result_loc); +} + +static IrInstSrc *ir_gen_if_err_expr(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, + ResultLoc *result_loc) +{ + assert(node->type == NodeTypeIfErrorExpr); + + AstNode *target_node = node->data.if_err_expr.target_node; + AstNode *then_node = node->data.if_err_expr.then_node; + AstNode *else_node = node->data.if_err_expr.else_node; + bool var_is_ptr = node->data.if_err_expr.var_is_ptr; + bool var_is_const = true; + Buf *var_symbol = node->data.if_err_expr.var_symbol; + Buf *err_symbol = node->data.if_err_expr.err_symbol; + + IrInstSrc *err_val_ptr = ir_gen_node_extra(irb, target_node, scope, LValPtr, nullptr); + if (err_val_ptr == irb->codegen->invalid_inst_src) + return err_val_ptr; + + IrInstSrc *err_val = ir_build_load_ptr(irb, scope, node, err_val_ptr); + IrInstSrc *is_err = ir_build_test_err_src(irb, scope, node, err_val_ptr, true, false); + + IrBasicBlockSrc *ok_block = ir_create_basic_block(irb, scope, "TryOk"); + IrBasicBlockSrc *else_block = ir_create_basic_block(irb, scope, "TryElse"); + IrBasicBlockSrc *endif_block = ir_create_basic_block(irb, scope, "TryEnd"); + + bool force_comptime = ir_should_inline(irb->exec, scope); + IrInstSrc *is_comptime = force_comptime ? ir_build_const_bool(irb, scope, node, true) : ir_build_test_comptime(irb, scope, node, is_err); + IrInstSrc *cond_br_inst = ir_build_cond_br(irb, scope, node, is_err, else_block, ok_block, is_comptime); + + ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, else_block, endif_block, + result_loc, is_comptime); + + ir_set_cursor_at_end_and_append_block(irb, ok_block); + + Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime); + Scope *var_scope; + if (var_symbol) { + bool is_shadowable = false; + IrInstSrc *var_is_comptime = force_comptime ? ir_build_const_bool(irb, subexpr_scope, node, true) : ir_build_test_comptime(irb, subexpr_scope, node, err_val); + ZigVar *var = ir_create_var(irb, node, subexpr_scope, + var_symbol, var_is_const, var_is_const, is_shadowable, var_is_comptime); + + IrInstSrc *payload_ptr = ir_build_unwrap_err_payload_src(irb, subexpr_scope, node, err_val_ptr, false, false); + IrInstSrc *var_value = var_is_ptr ? + payload_ptr : ir_build_load_ptr(irb, subexpr_scope, node, payload_ptr); + build_decl_var_and_init(irb, subexpr_scope, node, var, var_value, buf_ptr(var_symbol), var_is_comptime); + var_scope = var->child_scope; + } else { + var_scope = subexpr_scope; + } + IrInstSrc *then_expr_result = ir_gen_node_extra(irb, then_node, var_scope, lval, + &peer_parent->peers.at(0)->base); + if (then_expr_result == irb->codegen->invalid_inst_src) + return then_expr_result; + IrBasicBlockSrc *after_then_block = irb->current_basic_block; + if (!instr_is_unreachable(then_expr_result)) + ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime)); + + ir_set_cursor_at_end_and_append_block(irb, else_block); + + IrInstSrc *else_expr_result; + if (else_node) { + Scope *err_var_scope; + if (err_symbol) { + bool is_shadowable = false; + bool is_const = true; + ZigVar *var = ir_create_var(irb, node, subexpr_scope, + err_symbol, is_const, is_const, is_shadowable, is_comptime); + + IrInstSrc *err_ptr = ir_build_unwrap_err_code_src(irb, subexpr_scope, node, err_val_ptr); + IrInstSrc *err_value = ir_build_load_ptr(irb, subexpr_scope, node, err_ptr); + build_decl_var_and_init(irb, subexpr_scope, node, var, err_value, buf_ptr(err_symbol), is_comptime); + err_var_scope = var->child_scope; + } else { + err_var_scope = subexpr_scope; + } + else_expr_result = ir_gen_node_extra(irb, else_node, err_var_scope, lval, &peer_parent->peers.at(1)->base); + if (else_expr_result == irb->codegen->invalid_inst_src) + return else_expr_result; + } else { + else_expr_result = ir_build_const_void(irb, scope, node); + ir_build_end_expr(irb, scope, node, else_expr_result, &peer_parent->peers.at(1)->base); + } + IrBasicBlockSrc *after_else_block = irb->current_basic_block; + if (!instr_is_unreachable(else_expr_result)) + ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime)); + + ir_set_cursor_at_end_and_append_block(irb, endif_block); + IrInstSrc **incoming_values = heap::c_allocator.allocate(2); + incoming_values[0] = then_expr_result; + incoming_values[1] = else_expr_result; + IrBasicBlockSrc **incoming_blocks = heap::c_allocator.allocate(2); + incoming_blocks[0] = after_then_block; + incoming_blocks[1] = after_else_block; + + IrInstSrc *phi = ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, peer_parent); + return ir_expr_wrap(irb, scope, phi, result_loc); +} + +static bool ir_gen_switch_prong_expr(IrBuilderSrc *irb, Scope *scope, AstNode *switch_node, AstNode *prong_node, + IrBasicBlockSrc *end_block, IrInstSrc *is_comptime, IrInstSrc *var_is_comptime, + IrInstSrc *target_value_ptr, IrInstSrc **prong_values, size_t prong_values_len, + ZigList *incoming_blocks, ZigList *incoming_values, + IrInstSrcSwitchElseVar **out_switch_else_var, LVal lval, ResultLoc *result_loc) +{ + assert(switch_node->type == NodeTypeSwitchExpr); + assert(prong_node->type == NodeTypeSwitchProng); + + AstNode *expr_node = prong_node->data.switch_prong.expr; + AstNode *var_symbol_node = prong_node->data.switch_prong.var_symbol; + Scope *child_scope; + if (var_symbol_node) { + assert(var_symbol_node->type == NodeTypeIdentifier); + Buf *var_name = node_identifier_buf(var_symbol_node); + bool var_is_ptr = prong_node->data.switch_prong.var_is_ptr; + + bool is_shadowable = false; + bool is_const = true; + ZigVar *var = ir_create_var(irb, var_symbol_node, scope, + var_name, is_const, is_const, is_shadowable, var_is_comptime); + child_scope = var->child_scope; + IrInstSrc *var_value; + if (out_switch_else_var != nullptr) { + IrInstSrcSwitchElseVar *switch_else_var = ir_build_switch_else_var(irb, scope, var_symbol_node, + target_value_ptr); + *out_switch_else_var = switch_else_var; + IrInstSrc *payload_ptr = &switch_else_var->base; + var_value = var_is_ptr ? + payload_ptr : ir_build_load_ptr(irb, scope, var_symbol_node, payload_ptr); + } else if (prong_values != nullptr) { + IrInstSrc *payload_ptr = ir_build_switch_var(irb, scope, var_symbol_node, target_value_ptr, + prong_values, prong_values_len); + var_value = var_is_ptr ? + payload_ptr : ir_build_load_ptr(irb, scope, var_symbol_node, payload_ptr); + } else { + var_value = var_is_ptr ? + target_value_ptr : ir_build_load_ptr(irb, scope, var_symbol_node, target_value_ptr); + } + build_decl_var_and_init(irb, scope, var_symbol_node, var, var_value, buf_ptr(var_name), var_is_comptime); + } else { + child_scope = scope; + } + + IrInstSrc *expr_result = ir_gen_node_extra(irb, expr_node, child_scope, lval, result_loc); + if (expr_result == irb->codegen->invalid_inst_src) + return false; + if (!instr_is_unreachable(expr_result)) + ir_mark_gen(ir_build_br(irb, scope, switch_node, end_block, is_comptime)); + incoming_blocks->append(irb->current_basic_block); + incoming_values->append(expr_result); + return true; +} + +static IrInstSrc *ir_gen_switch_expr(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, + ResultLoc *result_loc) +{ + assert(node->type == NodeTypeSwitchExpr); + + AstNode *target_node = node->data.switch_expr.expr; + IrInstSrc *target_value_ptr = ir_gen_node_extra(irb, target_node, scope, LValPtr, nullptr); + if (target_value_ptr == irb->codegen->invalid_inst_src) + return target_value_ptr; + IrInstSrc *target_value = ir_build_switch_target(irb, scope, node, target_value_ptr); + + IrBasicBlockSrc *else_block = ir_create_basic_block(irb, scope, "SwitchElse"); + IrBasicBlockSrc *end_block = ir_create_basic_block(irb, scope, "SwitchEnd"); + + size_t prong_count = node->data.switch_expr.prongs.length; + ZigList cases = {0}; + + IrInstSrc *is_comptime; + IrInstSrc *var_is_comptime; + if (ir_should_inline(irb->exec, scope)) { + is_comptime = ir_build_const_bool(irb, scope, node, true); + var_is_comptime = is_comptime; + } else { + is_comptime = ir_build_test_comptime(irb, scope, node, target_value); + var_is_comptime = ir_build_test_comptime(irb, scope, node, target_value_ptr); + } + + ZigList incoming_values = {0}; + ZigList incoming_blocks = {0}; + ZigList check_ranges = {0}; + + IrInstSrcSwitchElseVar *switch_else_var = nullptr; + + ResultLocPeerParent *peer_parent = heap::c_allocator.create(); + peer_parent->base.id = ResultLocIdPeerParent; + peer_parent->base.allow_write_through_const = result_loc->allow_write_through_const; + peer_parent->end_bb = end_block; + peer_parent->is_comptime = is_comptime; + peer_parent->parent = result_loc; + + ir_build_reset_result(irb, scope, node, &peer_parent->base); + + // First do the else and the ranges + Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime); + Scope *comptime_scope = create_comptime_scope(irb->codegen, node, scope); + AstNode *else_prong = nullptr; + AstNode *underscore_prong = nullptr; + for (size_t prong_i = 0; prong_i < prong_count; prong_i += 1) { + AstNode *prong_node = node->data.switch_expr.prongs.at(prong_i); + size_t prong_item_count = prong_node->data.switch_prong.items.length; + if (prong_node->data.switch_prong.any_items_are_range) { + ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent); + + IrInstSrc *ok_bit = nullptr; + AstNode *last_item_node = nullptr; + for (size_t item_i = 0; item_i < prong_item_count; item_i += 1) { + AstNode *item_node = prong_node->data.switch_prong.items.at(item_i); + last_item_node = item_node; + if (item_node->type == NodeTypeSwitchRange) { + AstNode *start_node = item_node->data.switch_range.start; + AstNode *end_node = item_node->data.switch_range.end; + + IrInstSrc *start_value = ir_gen_node(irb, start_node, comptime_scope); + if (start_value == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + + IrInstSrc *end_value = ir_gen_node(irb, end_node, comptime_scope); + if (end_value == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + + IrInstSrcCheckSwitchProngsRange *check_range = check_ranges.add_one(); + check_range->start = start_value; + check_range->end = end_value; + + IrInstSrc *lower_range_ok = ir_build_bin_op(irb, scope, item_node, IrBinOpCmpGreaterOrEq, + target_value, start_value, false); + IrInstSrc *upper_range_ok = ir_build_bin_op(irb, scope, item_node, IrBinOpCmpLessOrEq, + target_value, end_value, false); + IrInstSrc *both_ok = ir_build_bin_op(irb, scope, item_node, IrBinOpBoolAnd, + lower_range_ok, upper_range_ok, false); + if (ok_bit) { + ok_bit = ir_build_bin_op(irb, scope, item_node, IrBinOpBoolOr, both_ok, ok_bit, false); + } else { + ok_bit = both_ok; + } + } else { + IrInstSrc *item_value = ir_gen_node(irb, item_node, comptime_scope); + if (item_value == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + + IrInstSrcCheckSwitchProngsRange *check_range = check_ranges.add_one(); + check_range->start = item_value; + check_range->end = item_value; + + IrInstSrc *cmp_ok = ir_build_bin_op(irb, scope, item_node, IrBinOpCmpEq, + item_value, target_value, false); + if (ok_bit) { + ok_bit = ir_build_bin_op(irb, scope, item_node, IrBinOpBoolOr, cmp_ok, ok_bit, false); + } else { + ok_bit = cmp_ok; + } + } + } + + IrBasicBlockSrc *range_block_yes = ir_create_basic_block(irb, scope, "SwitchRangeYes"); + IrBasicBlockSrc *range_block_no = ir_create_basic_block(irb, scope, "SwitchRangeNo"); + + assert(ok_bit); + assert(last_item_node); + IrInstSrc *br_inst = ir_mark_gen(ir_build_cond_br(irb, scope, last_item_node, ok_bit, + range_block_yes, range_block_no, is_comptime)); + if (peer_parent->base.source_instruction == nullptr) { + peer_parent->base.source_instruction = br_inst; + } + + if (peer_parent->peers.length > 0) { + peer_parent->peers.last()->next_bb = range_block_yes; + } + peer_parent->peers.append(this_peer_result_loc); + ir_set_cursor_at_end_and_append_block(irb, range_block_yes); + if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block, + is_comptime, var_is_comptime, target_value_ptr, nullptr, 0, + &incoming_blocks, &incoming_values, nullptr, LValNone, &this_peer_result_loc->base)) + { + return irb->codegen->invalid_inst_src; + } + + ir_set_cursor_at_end_and_append_block(irb, range_block_no); + } else { + if (prong_item_count == 0) { + if (else_prong) { + ErrorMsg *msg = add_node_error(irb->codegen, prong_node, + buf_sprintf("multiple else prongs in switch expression")); + add_error_note(irb->codegen, msg, else_prong, + buf_sprintf("previous else prong is here")); + return irb->codegen->invalid_inst_src; + } + else_prong = prong_node; + } else if (prong_item_count == 1 && + prong_node->data.switch_prong.items.at(0)->type == NodeTypeIdentifier && + buf_eql_str(node_identifier_buf(prong_node->data.switch_prong.items.at(0)), "_")) { + if (underscore_prong) { + ErrorMsg *msg = add_node_error(irb->codegen, prong_node, + buf_sprintf("multiple '_' prongs in switch expression")); + add_error_note(irb->codegen, msg, underscore_prong, + buf_sprintf("previous '_' prong is here")); + return irb->codegen->invalid_inst_src; + } + underscore_prong = prong_node; + } else { + continue; + } + if (underscore_prong && else_prong) { + ErrorMsg *msg = add_node_error(irb->codegen, prong_node, + buf_sprintf("else and '_' prong in switch expression")); + if (underscore_prong == prong_node) + add_error_note(irb->codegen, msg, else_prong, + buf_sprintf("else prong is here")); + else + add_error_note(irb->codegen, msg, underscore_prong, + buf_sprintf("'_' prong is here")); + return irb->codegen->invalid_inst_src; + } + ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent); + + IrBasicBlockSrc *prev_block = irb->current_basic_block; + if (peer_parent->peers.length > 0) { + peer_parent->peers.last()->next_bb = else_block; + } + peer_parent->peers.append(this_peer_result_loc); + ir_set_cursor_at_end_and_append_block(irb, else_block); + if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block, + is_comptime, var_is_comptime, target_value_ptr, nullptr, 0, &incoming_blocks, &incoming_values, + &switch_else_var, LValNone, &this_peer_result_loc->base)) + { + return irb->codegen->invalid_inst_src; + } + ir_set_cursor_at_end(irb, prev_block); + } + } + + // next do the non-else non-ranges + for (size_t prong_i = 0; prong_i < prong_count; prong_i += 1) { + AstNode *prong_node = node->data.switch_expr.prongs.at(prong_i); + size_t prong_item_count = prong_node->data.switch_prong.items.length; + if (prong_item_count == 0) + continue; + if (prong_node->data.switch_prong.any_items_are_range) + continue; + if (underscore_prong == prong_node) + continue; + + ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent); + + IrBasicBlockSrc *prong_block = ir_create_basic_block(irb, scope, "SwitchProng"); + IrInstSrc **items = heap::c_allocator.allocate(prong_item_count); + + for (size_t item_i = 0; item_i < prong_item_count; item_i += 1) { + AstNode *item_node = prong_node->data.switch_prong.items.at(item_i); + assert(item_node->type != NodeTypeSwitchRange); + + IrInstSrc *item_value = ir_gen_node(irb, item_node, comptime_scope); + if (item_value == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + + IrInstSrcCheckSwitchProngsRange *check_range = check_ranges.add_one(); + check_range->start = item_value; + check_range->end = item_value; + + IrInstSrcSwitchBrCase *this_case = cases.add_one(); + this_case->value = item_value; + this_case->block = prong_block; + + items[item_i] = item_value; + } + + IrBasicBlockSrc *prev_block = irb->current_basic_block; + if (peer_parent->peers.length > 0) { + peer_parent->peers.last()->next_bb = prong_block; + } + peer_parent->peers.append(this_peer_result_loc); + ir_set_cursor_at_end_and_append_block(irb, prong_block); + if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block, + is_comptime, var_is_comptime, target_value_ptr, items, prong_item_count, + &incoming_blocks, &incoming_values, nullptr, LValNone, &this_peer_result_loc->base)) + { + return irb->codegen->invalid_inst_src; + } + + ir_set_cursor_at_end(irb, prev_block); + + } + + IrInstSrc *switch_prongs_void = ir_build_check_switch_prongs(irb, scope, node, target_value, + check_ranges.items, check_ranges.length, else_prong, underscore_prong != nullptr); + + IrInstSrc *br_instruction; + if (cases.length == 0) { + br_instruction = ir_build_br(irb, scope, node, else_block, is_comptime); + } else { + IrInstSrcSwitchBr *switch_br = ir_build_switch_br_src(irb, scope, node, target_value, else_block, + cases.length, cases.items, is_comptime, switch_prongs_void); + if (switch_else_var != nullptr) { + switch_else_var->switch_br = switch_br; + } + br_instruction = &switch_br->base; + } + if (peer_parent->base.source_instruction == nullptr) { + peer_parent->base.source_instruction = br_instruction; + } + for (size_t i = 0; i < peer_parent->peers.length; i += 1) { + peer_parent->peers.at(i)->base.source_instruction = peer_parent->base.source_instruction; + } + + if (!else_prong && !underscore_prong) { + if (peer_parent->peers.length != 0) { + peer_parent->peers.last()->next_bb = else_block; + } + ir_set_cursor_at_end_and_append_block(irb, else_block); + ir_build_unreachable(irb, scope, node); + } else { + if (peer_parent->peers.length != 0) { + peer_parent->peers.last()->next_bb = end_block; + } + } + + ir_set_cursor_at_end_and_append_block(irb, end_block); + assert(incoming_blocks.length == incoming_values.length); + IrInstSrc *result_instruction; + if (incoming_blocks.length == 0) { + result_instruction = ir_build_const_void(irb, scope, node); + } else { + result_instruction = ir_build_phi(irb, scope, node, incoming_blocks.length, + incoming_blocks.items, incoming_values.items, peer_parent); + } + return ir_lval_wrap(irb, scope, result_instruction, lval, result_loc); +} + +static IrInstSrc *ir_gen_comptime(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node, LVal lval) { + assert(node->type == NodeTypeCompTime); + + Scope *child_scope = create_comptime_scope(irb->codegen, node, parent_scope); + // purposefully pass null for result_loc and let EndExpr handle it + return ir_gen_node_extra(irb, node->data.comptime_expr.expr, child_scope, lval, nullptr); +} + +static IrInstSrc *ir_gen_nosuspend(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node, LVal lval) { + assert(node->type == NodeTypeNoSuspend); + + Scope *child_scope = create_nosuspend_scope(irb->codegen, node, parent_scope); + // purposefully pass null for result_loc and let EndExpr handle it + return ir_gen_node_extra(irb, node->data.nosuspend_expr.expr, child_scope, lval, nullptr); +} + +static IrInstSrc *ir_gen_return_from_block(IrBuilderSrc *irb, Scope *break_scope, AstNode *node, ScopeBlock *block_scope) { + IrInstSrc *is_comptime; + if (ir_should_inline(irb->exec, break_scope)) { + is_comptime = ir_build_const_bool(irb, break_scope, node, true); + } else { + is_comptime = block_scope->is_comptime; + } + + IrInstSrc *result_value; + if (node->data.break_expr.expr) { + ResultLocPeer *peer_result = create_peer_result(block_scope->peer_parent); + block_scope->peer_parent->peers.append(peer_result); + + result_value = ir_gen_node_extra(irb, node->data.break_expr.expr, break_scope, block_scope->lval, + &peer_result->base); + if (result_value == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + } else { + result_value = ir_build_const_void(irb, break_scope, node); + } + + IrBasicBlockSrc *dest_block = block_scope->end_block; + if (!ir_gen_defers_for_block(irb, break_scope, dest_block->scope, nullptr, nullptr)) + return irb->codegen->invalid_inst_src; + + block_scope->incoming_blocks->append(irb->current_basic_block); + block_scope->incoming_values->append(result_value); + return ir_build_br(irb, break_scope, node, dest_block, is_comptime); +} + +static IrInstSrc *ir_gen_break(IrBuilderSrc *irb, Scope *break_scope, AstNode *node) { + assert(node->type == NodeTypeBreak); + + // Search up the scope. We'll find one of these things first: + // * function definition scope or global scope => error, break outside loop + // * defer expression scope => error, cannot break out of defer expression + // * loop scope => OK + // * (if it's a labeled break) labeled block => OK + + Scope *search_scope = break_scope; + ScopeLoop *loop_scope; + for (;;) { + if (search_scope == nullptr || search_scope->id == ScopeIdFnDef) { + if (node->data.break_expr.name != nullptr) { + add_node_error(irb->codegen, node, buf_sprintf("label not found: '%s'", buf_ptr(node->data.break_expr.name))); + return irb->codegen->invalid_inst_src; + } else { + add_node_error(irb->codegen, node, buf_sprintf("break expression outside loop")); + return irb->codegen->invalid_inst_src; + } + } else if (search_scope->id == ScopeIdDeferExpr) { + add_node_error(irb->codegen, node, buf_sprintf("cannot break out of defer expression")); + return irb->codegen->invalid_inst_src; + } else if (search_scope->id == ScopeIdLoop) { + ScopeLoop *this_loop_scope = (ScopeLoop *)search_scope; + if (node->data.break_expr.name == nullptr || + (this_loop_scope->name != nullptr && buf_eql_buf(node->data.break_expr.name, this_loop_scope->name))) + { + this_loop_scope->name_used = true; + loop_scope = this_loop_scope; + break; + } + } else if (search_scope->id == ScopeIdBlock) { + ScopeBlock *this_block_scope = (ScopeBlock *)search_scope; + if (node->data.break_expr.name != nullptr && + (this_block_scope->name != nullptr && buf_eql_buf(node->data.break_expr.name, this_block_scope->name))) + { + assert(this_block_scope->end_block != nullptr); + this_block_scope->name_used = true; + return ir_gen_return_from_block(irb, break_scope, node, this_block_scope); + } + } else if (search_scope->id == ScopeIdSuspend) { + add_node_error(irb->codegen, node, buf_sprintf("cannot break out of suspend block")); + return irb->codegen->invalid_inst_src; + } + search_scope = search_scope->parent; + } + + IrInstSrc *is_comptime; + if (ir_should_inline(irb->exec, break_scope)) { + is_comptime = ir_build_const_bool(irb, break_scope, node, true); + } else { + is_comptime = loop_scope->is_comptime; + } + + IrInstSrc *result_value; + if (node->data.break_expr.expr) { + ResultLocPeer *peer_result = create_peer_result(loop_scope->peer_parent); + loop_scope->peer_parent->peers.append(peer_result); + + result_value = ir_gen_node_extra(irb, node->data.break_expr.expr, break_scope, + loop_scope->lval, &peer_result->base); + if (result_value == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + } else { + result_value = ir_build_const_void(irb, break_scope, node); + } + + IrBasicBlockSrc *dest_block = loop_scope->break_block; + if (!ir_gen_defers_for_block(irb, break_scope, dest_block->scope, nullptr, nullptr)) + return irb->codegen->invalid_inst_src; + + loop_scope->incoming_blocks->append(irb->current_basic_block); + loop_scope->incoming_values->append(result_value); + return ir_build_br(irb, break_scope, node, dest_block, is_comptime); +} + +static IrInstSrc *ir_gen_continue(IrBuilderSrc *irb, Scope *continue_scope, AstNode *node) { + assert(node->type == NodeTypeContinue); + + // Search up the scope. We'll find one of these things first: + // * function definition scope or global scope => error, break outside loop + // * defer expression scope => error, cannot break out of defer expression + // * loop scope => OK + + ZigList runtime_scopes = {}; + + Scope *search_scope = continue_scope; + ScopeLoop *loop_scope; + for (;;) { + if (search_scope == nullptr || search_scope->id == ScopeIdFnDef) { + if (node->data.continue_expr.name != nullptr) { + add_node_error(irb->codegen, node, buf_sprintf("labeled loop not found: '%s'", buf_ptr(node->data.continue_expr.name))); + return irb->codegen->invalid_inst_src; + } else { + add_node_error(irb->codegen, node, buf_sprintf("continue expression outside loop")); + return irb->codegen->invalid_inst_src; + } + } else if (search_scope->id == ScopeIdDeferExpr) { + add_node_error(irb->codegen, node, buf_sprintf("cannot continue out of defer expression")); + return irb->codegen->invalid_inst_src; + } else if (search_scope->id == ScopeIdLoop) { + ScopeLoop *this_loop_scope = (ScopeLoop *)search_scope; + if (node->data.continue_expr.name == nullptr || + (this_loop_scope->name != nullptr && buf_eql_buf(node->data.continue_expr.name, this_loop_scope->name))) + { + this_loop_scope->name_used = true; + loop_scope = this_loop_scope; + break; + } + } else if (search_scope->id == ScopeIdRuntime) { + ScopeRuntime *scope_runtime = (ScopeRuntime *)search_scope; + runtime_scopes.append(scope_runtime); + } + search_scope = search_scope->parent; + } + + IrInstSrc *is_comptime; + if (ir_should_inline(irb->exec, continue_scope)) { + is_comptime = ir_build_const_bool(irb, continue_scope, node, true); + } else { + is_comptime = loop_scope->is_comptime; + } + + for (size_t i = 0; i < runtime_scopes.length; i += 1) { + ScopeRuntime *scope_runtime = runtime_scopes.at(i); + ir_mark_gen(ir_build_check_runtime_scope(irb, continue_scope, node, scope_runtime->is_comptime, is_comptime)); + } + runtime_scopes.deinit(); + + IrBasicBlockSrc *dest_block = loop_scope->continue_block; + if (!ir_gen_defers_for_block(irb, continue_scope, dest_block->scope, nullptr, nullptr)) + return irb->codegen->invalid_inst_src; + return ir_mark_gen(ir_build_br(irb, continue_scope, node, dest_block, is_comptime)); +} + +static IrInstSrc *ir_gen_error_type(IrBuilderSrc *irb, Scope *scope, AstNode *node) { + assert(node->type == NodeTypeErrorType); + return ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_global_error_set); +} + +static IrInstSrc *ir_gen_defer(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node) { + assert(node->type == NodeTypeDefer); + + ScopeDefer *defer_child_scope = create_defer_scope(irb->codegen, node, parent_scope); + node->data.defer.child_scope = &defer_child_scope->base; + + ScopeDeferExpr *defer_expr_scope = create_defer_expr_scope(irb->codegen, node, parent_scope); + node->data.defer.expr_scope = &defer_expr_scope->base; + + return ir_build_const_void(irb, parent_scope, node); +} + +static IrInstSrc *ir_gen_slice(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { + assert(node->type == NodeTypeSliceExpr); + + AstNodeSliceExpr *slice_expr = &node->data.slice_expr; + AstNode *array_node = slice_expr->array_ref_expr; + AstNode *start_node = slice_expr->start; + AstNode *end_node = slice_expr->end; + AstNode *sentinel_node = slice_expr->sentinel; + + IrInstSrc *ptr_value = ir_gen_node_extra(irb, array_node, scope, LValPtr, nullptr); + if (ptr_value == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + + IrInstSrc *start_value = ir_gen_node(irb, start_node, scope); + if (start_value == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + + IrInstSrc *end_value; + if (end_node) { + end_value = ir_gen_node(irb, end_node, scope); + if (end_value == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + } else { + end_value = nullptr; + } + + IrInstSrc *sentinel_value; + if (sentinel_node) { + sentinel_value = ir_gen_node(irb, sentinel_node, scope); + if (sentinel_value == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + } else { + sentinel_value = nullptr; + } + + IrInstSrc *slice = ir_build_slice_src(irb, scope, node, ptr_value, start_value, end_value, + sentinel_value, true, result_loc); + return ir_lval_wrap(irb, scope, slice, lval, result_loc); +} + +static IrInstSrc *ir_gen_catch(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node, LVal lval, + ResultLoc *result_loc) +{ + assert(node->type == NodeTypeCatchExpr); + + AstNode *op1_node = node->data.unwrap_err_expr.op1; + AstNode *op2_node = node->data.unwrap_err_expr.op2; + AstNode *var_node = node->data.unwrap_err_expr.symbol; + + if (op2_node->type == NodeTypeUnreachable) { + if (var_node != nullptr) { + assert(var_node->type == NodeTypeIdentifier); + Buf *var_name = node_identifier_buf(var_node); + add_node_error(irb->codegen, var_node, buf_sprintf("unused variable: '%s'", buf_ptr(var_name))); + return irb->codegen->invalid_inst_src; + } + return ir_gen_catch_unreachable(irb, parent_scope, node, op1_node, lval, result_loc); + } + + + ScopeExpr *spill_scope = create_expr_scope(irb->codegen, op1_node, parent_scope); + spill_scope->spill_harder = true; + + IrInstSrc *err_union_ptr = ir_gen_node_extra(irb, op1_node, &spill_scope->base, LValPtr, nullptr); + if (err_union_ptr == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + + IrInstSrc *is_err = ir_build_test_err_src(irb, parent_scope, node, err_union_ptr, true, false); + + IrInstSrc *is_comptime; + if (ir_should_inline(irb->exec, parent_scope)) { + is_comptime = ir_build_const_bool(irb, parent_scope, node, true); + } else { + is_comptime = ir_build_test_comptime(irb, parent_scope, node, is_err); + } + + IrBasicBlockSrc *ok_block = ir_create_basic_block(irb, parent_scope, "UnwrapErrOk"); + IrBasicBlockSrc *err_block = ir_create_basic_block(irb, parent_scope, "UnwrapErrError"); + IrBasicBlockSrc *end_block = ir_create_basic_block(irb, parent_scope, "UnwrapErrEnd"); + IrInstSrc *cond_br_inst = ir_build_cond_br(irb, parent_scope, node, is_err, err_block, ok_block, is_comptime); + + ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, ok_block, end_block, result_loc, + is_comptime); + + ir_set_cursor_at_end_and_append_block(irb, err_block); + Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, &spill_scope->base, is_comptime); + Scope *err_scope; + if (var_node) { + assert(var_node->type == NodeTypeIdentifier); + Buf *var_name = node_identifier_buf(var_node); + bool is_const = true; + bool is_shadowable = false; + ZigVar *var = ir_create_var(irb, node, subexpr_scope, var_name, + is_const, is_const, is_shadowable, is_comptime); + err_scope = var->child_scope; + IrInstSrc *err_ptr = ir_build_unwrap_err_code_src(irb, err_scope, node, err_union_ptr); + IrInstSrc *err_value = ir_build_load_ptr(irb, err_scope, var_node, err_ptr); + build_decl_var_and_init(irb, err_scope, var_node, var, err_value, buf_ptr(var_name), is_comptime); + } else { + err_scope = subexpr_scope; + } + IrInstSrc *err_result = ir_gen_node_extra(irb, op2_node, err_scope, LValNone, &peer_parent->peers.at(0)->base); + if (err_result == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + IrBasicBlockSrc *after_err_block = irb->current_basic_block; + if (!instr_is_unreachable(err_result)) + ir_mark_gen(ir_build_br(irb, parent_scope, node, end_block, is_comptime)); + + ir_set_cursor_at_end_and_append_block(irb, ok_block); + IrInstSrc *unwrapped_ptr = ir_build_unwrap_err_payload_src(irb, parent_scope, node, err_union_ptr, false, false); + IrInstSrc *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr); + ir_build_end_expr(irb, parent_scope, node, unwrapped_payload, &peer_parent->peers.at(1)->base); + IrBasicBlockSrc *after_ok_block = irb->current_basic_block; + ir_build_br(irb, parent_scope, node, end_block, is_comptime); + + ir_set_cursor_at_end_and_append_block(irb, end_block); + IrInstSrc **incoming_values = heap::c_allocator.allocate(2); + incoming_values[0] = err_result; + incoming_values[1] = unwrapped_payload; + IrBasicBlockSrc **incoming_blocks = heap::c_allocator.allocate(2); + incoming_blocks[0] = after_err_block; + incoming_blocks[1] = after_ok_block; + IrInstSrc *phi = ir_build_phi(irb, parent_scope, node, 2, incoming_blocks, incoming_values, peer_parent); + return ir_lval_wrap(irb, parent_scope, phi, lval, result_loc); +} + +static bool render_instance_name_recursive(CodeGen *codegen, Buf *name, Scope *outer_scope, Scope *inner_scope) { + if (inner_scope == nullptr || inner_scope == outer_scope) return false; + bool need_comma = render_instance_name_recursive(codegen, name, outer_scope, inner_scope->parent); + if (inner_scope->id != ScopeIdVarDecl) + return need_comma; + + ScopeVarDecl *var_scope = (ScopeVarDecl *)inner_scope; + if (need_comma) + buf_append_char(name, ','); + // TODO: const ptr reinterpret here to make the var type agree with the value? + render_const_value(codegen, name, var_scope->var->const_value); + return true; +} + +Buf *get_anon_type_name(CodeGen *codegen, IrExecutableSrc *exec, const char *kind_name, + Scope *scope, AstNode *source_node, Buf *out_bare_name) +{ + if (exec != nullptr && exec->name) { + ZigType *import = get_scope_import(scope); + Buf *namespace_name = buf_alloc(); + append_namespace_qualification(codegen, namespace_name, import); + buf_append_buf(namespace_name, exec->name); + buf_init_from_buf(out_bare_name, exec->name); + return namespace_name; + } else if (exec != nullptr && exec->name_fn != nullptr) { + Buf *name = buf_alloc(); + buf_append_buf(name, &exec->name_fn->symbol_name); + buf_appendf(name, "("); + render_instance_name_recursive(codegen, name, &exec->name_fn->fndef_scope->base, exec->begin_scope); + buf_appendf(name, ")"); + buf_init_from_buf(out_bare_name, name); + return name; + } else { + ZigType *import = get_scope_import(scope); + Buf *namespace_name = buf_alloc(); + append_namespace_qualification(codegen, namespace_name, import); + RootStruct *root_struct = source_node->owner->data.structure.root_struct; + TokenLoc tok_loc = root_struct->token_locs[source_node->main_token]; + buf_appendf(namespace_name, "%s:%u:%u", kind_name, + tok_loc.line + 1, tok_loc.column + 1); + buf_init_from_buf(out_bare_name, namespace_name); + return namespace_name; + } +} + +static IrInstSrc *ir_gen_container_decl(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node) { + assert(node->type == NodeTypeContainerDecl); + + ContainerKind kind = node->data.container_decl.kind; + Buf *bare_name = buf_alloc(); + Buf *name = get_anon_type_name(irb->codegen, irb->exec, container_string(kind), parent_scope, node, bare_name); + + ContainerLayout layout = node->data.container_decl.layout; + ZigType *container_type = get_partial_container_type(irb->codegen, parent_scope, + kind, node, buf_ptr(name), bare_name, layout); + ScopeDecls *child_scope = get_container_scope(container_type); + + for (size_t i = 0; i < node->data.container_decl.decls.length; i += 1) { + AstNode *child_node = node->data.container_decl.decls.at(i); + scan_decls(irb->codegen, child_scope, child_node); + } + + TldContainer *tld_container = heap::c_allocator.create(); + init_tld(&tld_container->base, TldIdContainer, bare_name, VisibModPub, node, parent_scope); + tld_container->type_entry = container_type; + tld_container->decls_scope = child_scope; + irb->codegen->resolve_queue.append(&tld_container->base); + + // Add this to the list to mark as invalid if analyzing this exec fails. + irb->exec->tld_list.append(&tld_container->base); + + return ir_build_const_type(irb, parent_scope, node, container_type); +} + +static IrInstSrc *ir_gen_err_set_decl(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node) { + assert(node->type == NodeTypeErrorSetDecl); + + uint32_t err_count = node->data.err_set_decl.decls.length; + + Buf bare_name = BUF_INIT; + Buf *type_name = get_anon_type_name(irb->codegen, irb->exec, "error", parent_scope, node, &bare_name); + ZigType *err_set_type = new_type_table_entry(ZigTypeIdErrorSet); + buf_init_from_buf(&err_set_type->name, type_name); + err_set_type->data.error_set.err_count = err_count; + err_set_type->size_in_bits = irb->codegen->builtin_types.entry_global_error_set->size_in_bits; + err_set_type->abi_align = irb->codegen->builtin_types.entry_global_error_set->abi_align; + err_set_type->abi_size = irb->codegen->builtin_types.entry_global_error_set->abi_size; + err_set_type->data.error_set.errors = heap::c_allocator.allocate(err_count); + + size_t errors_count = irb->codegen->errors_by_index.length + err_count; + ErrorTableEntry **errors = heap::c_allocator.allocate(errors_count); + + for (uint32_t i = 0; i < err_count; i += 1) { + AstNode *field_node = node->data.err_set_decl.decls.at(i); + AstNode *symbol_node = ast_field_to_symbol_node(field_node); + Buf *err_name = node_identifier_buf(symbol_node); + ErrorTableEntry *err = heap::c_allocator.create(); + err->decl_node = field_node; + buf_init_from_buf(&err->name, err_name); + + auto existing_entry = irb->codegen->error_table.put_unique(err_name, err); + if (existing_entry) { + err->value = existing_entry->value->value; + } else { + size_t error_value_count = irb->codegen->errors_by_index.length; + assert((uint32_t)error_value_count < (((uint32_t)1) << (uint32_t)irb->codegen->err_tag_type->data.integral.bit_count)); + err->value = error_value_count; + irb->codegen->errors_by_index.append(err); + } + err_set_type->data.error_set.errors[i] = err; + + ErrorTableEntry *prev_err = errors[err->value]; + if (prev_err != nullptr) { + ErrorMsg *msg = add_node_error(irb->codegen, ast_field_to_symbol_node(err->decl_node), + buf_sprintf("duplicate error: '%s'", buf_ptr(&err->name))); + add_error_note(irb->codegen, msg, ast_field_to_symbol_node(prev_err->decl_node), + buf_sprintf("other error here")); + return irb->codegen->invalid_inst_src; + } + errors[err->value] = err; + } + heap::c_allocator.deallocate(errors, errors_count); + return ir_build_const_type(irb, parent_scope, node, err_set_type); +} + +static IrInstSrc *ir_gen_fn_proto(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node) { + assert(node->type == NodeTypeFnProto); + + size_t param_count = node->data.fn_proto.params.length; + IrInstSrc **param_types = heap::c_allocator.allocate(param_count); + + bool is_var_args = false; + for (size_t i = 0; i < param_count; i += 1) { + AstNode *param_node = node->data.fn_proto.params.at(i); + if (param_node->data.param_decl.is_var_args) { + is_var_args = true; + break; + } + if (param_node->data.param_decl.anytype_token == 0) { + AstNode *type_node = param_node->data.param_decl.type; + IrInstSrc *type_value = ir_gen_node(irb, type_node, parent_scope); + if (type_value == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + param_types[i] = type_value; + } else { + param_types[i] = nullptr; + } + } + + IrInstSrc *align_value = nullptr; + if (node->data.fn_proto.align_expr != nullptr) { + align_value = ir_gen_node(irb, node->data.fn_proto.align_expr, parent_scope); + if (align_value == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + } + + IrInstSrc *callconv_value = nullptr; + if (node->data.fn_proto.callconv_expr != nullptr) { + callconv_value = ir_gen_node(irb, node->data.fn_proto.callconv_expr, parent_scope); + if (callconv_value == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + } + + IrInstSrc *return_type; + if (node->data.fn_proto.return_type == nullptr) { + return_type = ir_build_const_type(irb, parent_scope, node, irb->codegen->builtin_types.entry_void); + } else { + return_type = ir_gen_node(irb, node->data.fn_proto.return_type, parent_scope); + if (return_type == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + } + + return ir_build_fn_proto(irb, parent_scope, node, param_types, align_value, callconv_value, return_type, is_var_args); +} + +static IrInstSrc *ir_gen_resume(IrBuilderSrc *irb, Scope *scope, AstNode *node) { + assert(node->type == NodeTypeResume); + + IrInstSrc *target_inst = ir_gen_node_extra(irb, node->data.resume_expr.expr, scope, LValPtr, nullptr); + if (target_inst == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + + return ir_build_resume_src(irb, scope, node, target_inst); +} + +static IrInstSrc *ir_gen_await_expr(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, + ResultLoc *result_loc) +{ + assert(node->type == NodeTypeAwaitExpr); + + bool is_nosuspend = get_scope_nosuspend(scope) != nullptr; + + AstNode *expr_node = node->data.await_expr.expr; + if (expr_node->type == NodeTypeFnCallExpr && expr_node->data.fn_call_expr.modifier == CallModifierBuiltin) { + AstNode *fn_ref_expr = expr_node->data.fn_call_expr.fn_ref_expr; + Buf *name = node_identifier_buf(fn_ref_expr); + auto entry = irb->codegen->builtin_fn_table.maybe_get(name); + if (entry != nullptr) { + BuiltinFnEntry *builtin_fn = entry->value; + if (builtin_fn->id == BuiltinFnIdAsyncCall) { + return ir_gen_async_call(irb, scope, node, expr_node, lval, result_loc); + } + } + } + + ZigFn *fn_entry = exec_fn_entry(irb->exec); + if (!fn_entry) { + add_node_error(irb->codegen, node, buf_sprintf("await outside function definition")); + return irb->codegen->invalid_inst_src; + } + ScopeSuspend *existing_suspend_scope = get_scope_suspend(scope); + if (existing_suspend_scope) { + if (!existing_suspend_scope->reported_err) { + ErrorMsg *msg = add_node_error(irb->codegen, node, buf_sprintf("cannot await inside suspend block")); + add_error_note(irb->codegen, msg, existing_suspend_scope->base.source_node, buf_sprintf("suspend block here")); + existing_suspend_scope->reported_err = true; + } + return irb->codegen->invalid_inst_src; + } + + IrInstSrc *target_inst = ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr); + if (target_inst == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + + IrInstSrc *await_inst = ir_build_await_src(irb, scope, node, target_inst, result_loc, is_nosuspend); + return ir_lval_wrap(irb, scope, await_inst, lval, result_loc); +} + +static IrInstSrc *ir_gen_suspend(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node) { + assert(node->type == NodeTypeSuspend); + + ZigFn *fn_entry = exec_fn_entry(irb->exec); + if (!fn_entry) { + add_node_error(irb->codegen, node, buf_sprintf("suspend outside function definition")); + return irb->codegen->invalid_inst_src; + } + if (get_scope_nosuspend(parent_scope) != nullptr) { + add_node_error(irb->codegen, node, buf_sprintf("suspend in nosuspend scope")); + return irb->codegen->invalid_inst_src; + } + + ScopeSuspend *existing_suspend_scope = get_scope_suspend(parent_scope); + if (existing_suspend_scope) { + if (!existing_suspend_scope->reported_err) { + ErrorMsg *msg = add_node_error(irb->codegen, node, buf_sprintf("cannot suspend inside suspend block")); + add_error_note(irb->codegen, msg, existing_suspend_scope->base.source_node, buf_sprintf("other suspend block here")); + existing_suspend_scope->reported_err = true; + } + return irb->codegen->invalid_inst_src; + } + + IrInstSrcSuspendBegin *begin = ir_build_suspend_begin_src(irb, parent_scope, node); + ScopeSuspend *suspend_scope = create_suspend_scope(irb->codegen, node, parent_scope); + Scope *child_scope = &suspend_scope->base; + IrInstSrc *susp_res = ir_gen_node(irb, node->data.suspend.block, child_scope); + if (susp_res == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + ir_mark_gen(ir_build_check_statement_is_void(irb, child_scope, node->data.suspend.block, susp_res)); + + return ir_mark_gen(ir_build_suspend_finish_src(irb, parent_scope, node, begin)); +} + +static IrInstSrc *ir_gen_node_raw(IrBuilderSrc *irb, AstNode *node, Scope *scope, + LVal lval, ResultLoc *result_loc) +{ + assert(scope); + switch (node->type) { + case NodeTypeStructValueField: + case NodeTypeParamDecl: + case NodeTypeUsingNamespace: + case NodeTypeSwitchProng: + case NodeTypeSwitchRange: + case NodeTypeStructField: + case NodeTypeErrorSetField: + case NodeTypeFnDef: + case NodeTypeTestDecl: + zig_unreachable(); + case NodeTypeBlock: + return ir_gen_block(irb, scope, node, lval, result_loc); + case NodeTypeGroupedExpr: + return ir_gen_node_raw(irb, node->data.grouped_expr, scope, lval, result_loc); + case NodeTypeBinOpExpr: + return ir_gen_bin_op(irb, scope, node, lval, result_loc); + case NodeTypeIntLiteral: + return ir_lval_wrap(irb, scope, ir_gen_int_lit(irb, scope, node), lval, result_loc); + case NodeTypeFloatLiteral: + return ir_lval_wrap(irb, scope, ir_gen_float_lit(irb, scope, node), lval, result_loc); + case NodeTypeCharLiteral: + return ir_lval_wrap(irb, scope, ir_gen_char_lit(irb, scope, node), lval, result_loc); + case NodeTypeIdentifier: + return ir_gen_symbol(irb, scope, node, lval, result_loc); + case NodeTypeFnCallExpr: + return ir_gen_fn_call(irb, scope, node, lval, result_loc); + case NodeTypeIfBoolExpr: + return ir_gen_if_bool_expr(irb, scope, node, lval, result_loc); + case NodeTypePrefixOpExpr: + return ir_gen_prefix_op_expr(irb, scope, node, lval, result_loc); + case NodeTypeContainerInitExpr: + return ir_gen_container_init_expr(irb, scope, node, lval, result_loc); + case NodeTypeVariableDeclaration: + return ir_gen_var_decl(irb, scope, node); + case NodeTypeWhileExpr: + return ir_gen_while_expr(irb, scope, node, lval, result_loc); + case NodeTypeForExpr: + return ir_gen_for_expr(irb, scope, node, lval, result_loc); + case NodeTypeArrayAccessExpr: + return ir_gen_array_access(irb, scope, node, lval, result_loc); + case NodeTypeReturnExpr: + return ir_gen_return(irb, scope, node, lval, result_loc); + case NodeTypeFieldAccessExpr: + { + IrInstSrc *ptr_instruction = ir_gen_field_access(irb, scope, node); + if (ptr_instruction == irb->codegen->invalid_inst_src) + return ptr_instruction; + if (lval == LValPtr || lval == LValAssign) + return ptr_instruction; + + IrInstSrc *load_ptr = ir_build_load_ptr(irb, scope, node, ptr_instruction); + return ir_expr_wrap(irb, scope, load_ptr, result_loc); + } + case NodeTypePtrDeref: { + AstNode *expr_node = node->data.ptr_deref_expr.target; + + LVal child_lval = lval; + if (child_lval == LValAssign) + child_lval = LValPtr; + + IrInstSrc *value = ir_gen_node_extra(irb, expr_node, scope, child_lval, nullptr); + if (value == irb->codegen->invalid_inst_src) + return value; + + // We essentially just converted any lvalue from &(x.*) to (&x).*; + // this inhibits checking that x is a pointer later, so we directly + // record whether the pointer check is needed + IrInstSrc *un_op = ir_build_un_op_lval(irb, scope, node, IrUnOpDereference, value, lval, result_loc); + return ir_expr_wrap(irb, scope, un_op, result_loc); + } + case NodeTypeUnwrapOptional: { + AstNode *expr_node = node->data.unwrap_optional.expr; + + IrInstSrc *maybe_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr); + if (maybe_ptr == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + + IrInstSrc *unwrapped_ptr = ir_build_optional_unwrap_ptr(irb, scope, node, maybe_ptr, true ); + if (lval == LValPtr || lval == LValAssign) + return unwrapped_ptr; + + IrInstSrc *load_ptr = ir_build_load_ptr(irb, scope, node, unwrapped_ptr); + return ir_expr_wrap(irb, scope, load_ptr, result_loc); + } + case NodeTypeBoolLiteral: + return ir_lval_wrap(irb, scope, ir_gen_bool_literal(irb, scope, node), lval, result_loc); + case NodeTypeArrayType: + return ir_lval_wrap(irb, scope, ir_gen_array_type(irb, scope, node), lval, result_loc); + case NodeTypePointerType: + return ir_lval_wrap(irb, scope, ir_gen_pointer_type(irb, scope, node), lval, result_loc); + case NodeTypeAnyFrameType: + return ir_lval_wrap(irb, scope, ir_gen_anyframe_type(irb, scope, node), lval, result_loc); + case NodeTypeStringLiteral: + return ir_lval_wrap(irb, scope, ir_gen_string_literal(irb, scope, node), lval, result_loc); + case NodeTypeUndefinedLiteral: + return ir_lval_wrap(irb, scope, ir_gen_undefined_literal(irb, scope, node), lval, result_loc); + case NodeTypeAsmExpr: + return ir_lval_wrap(irb, scope, ir_gen_asm_expr(irb, scope, node), lval, result_loc); + case NodeTypeNullLiteral: + return ir_lval_wrap(irb, scope, ir_gen_null_literal(irb, scope, node), lval, result_loc); + case NodeTypeIfErrorExpr: + return ir_gen_if_err_expr(irb, scope, node, lval, result_loc); + case NodeTypeIfOptional: + return ir_gen_if_optional_expr(irb, scope, node, lval, result_loc); + case NodeTypeSwitchExpr: + return ir_gen_switch_expr(irb, scope, node, lval, result_loc); + case NodeTypeCompTime: + return ir_expr_wrap(irb, scope, ir_gen_comptime(irb, scope, node, lval), result_loc); + case NodeTypeNoSuspend: + return ir_expr_wrap(irb, scope, ir_gen_nosuspend(irb, scope, node, lval), result_loc); + case NodeTypeErrorType: + return ir_lval_wrap(irb, scope, ir_gen_error_type(irb, scope, node), lval, result_loc); + case NodeTypeBreak: + return ir_lval_wrap(irb, scope, ir_gen_break(irb, scope, node), lval, result_loc); + case NodeTypeContinue: + return ir_lval_wrap(irb, scope, ir_gen_continue(irb, scope, node), lval, result_loc); + case NodeTypeUnreachable: + return ir_build_unreachable(irb, scope, node); + case NodeTypeDefer: + return ir_lval_wrap(irb, scope, ir_gen_defer(irb, scope, node), lval, result_loc); + case NodeTypeSliceExpr: + return ir_gen_slice(irb, scope, node, lval, result_loc); + case NodeTypeCatchExpr: + return ir_gen_catch(irb, scope, node, lval, result_loc); + case NodeTypeContainerDecl: + return ir_lval_wrap(irb, scope, ir_gen_container_decl(irb, scope, node), lval, result_loc); + case NodeTypeFnProto: + return ir_lval_wrap(irb, scope, ir_gen_fn_proto(irb, scope, node), lval, result_loc); + case NodeTypeErrorSetDecl: + return ir_lval_wrap(irb, scope, ir_gen_err_set_decl(irb, scope, node), lval, result_loc); + case NodeTypeResume: + return ir_lval_wrap(irb, scope, ir_gen_resume(irb, scope, node), lval, result_loc); + case NodeTypeAwaitExpr: + return ir_gen_await_expr(irb, scope, node, lval, result_loc); + case NodeTypeSuspend: + return ir_lval_wrap(irb, scope, ir_gen_suspend(irb, scope, node), lval, result_loc); + case NodeTypeEnumLiteral: + return ir_lval_wrap(irb, scope, ir_gen_enum_literal(irb, scope, node), lval, result_loc); + case NodeTypeInferredArrayType: + add_node_error(irb->codegen, node, + buf_sprintf("inferred array size invalid here")); + return irb->codegen->invalid_inst_src; + case NodeTypeAnyTypeField: + return ir_lval_wrap(irb, scope, + ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_anytype), lval, result_loc); + } + zig_unreachable(); +} + +ResultLoc *no_result_loc(void) { + ResultLocNone *result_loc_none = heap::c_allocator.create(); + result_loc_none->base.id = ResultLocIdNone; + return &result_loc_none->base; +} + +static IrInstSrc *ir_gen_node_extra(IrBuilderSrc *irb, AstNode *node, Scope *scope, LVal lval, + ResultLoc *result_loc) +{ + if (lval == LValAssign) { + switch (node->type) { + case NodeTypeStructValueField: + case NodeTypeParamDecl: + case NodeTypeUsingNamespace: + case NodeTypeSwitchProng: + case NodeTypeSwitchRange: + case NodeTypeStructField: + case NodeTypeErrorSetField: + case NodeTypeFnDef: + case NodeTypeTestDecl: + zig_unreachable(); + + // cannot be assigned to + case NodeTypeBlock: + case NodeTypeGroupedExpr: + case NodeTypeBinOpExpr: + case NodeTypeIntLiteral: + case NodeTypeFloatLiteral: + case NodeTypeCharLiteral: + case NodeTypeIfBoolExpr: + case NodeTypeContainerInitExpr: + case NodeTypeVariableDeclaration: + case NodeTypeWhileExpr: + case NodeTypeForExpr: + case NodeTypeReturnExpr: + case NodeTypeBoolLiteral: + case NodeTypeArrayType: + case NodeTypePointerType: + case NodeTypeAnyFrameType: + case NodeTypeStringLiteral: + case NodeTypeUndefinedLiteral: + case NodeTypeAsmExpr: + case NodeTypeNullLiteral: + case NodeTypeIfErrorExpr: + case NodeTypeIfOptional: + case NodeTypeSwitchExpr: + case NodeTypeCompTime: + case NodeTypeNoSuspend: + case NodeTypeErrorType: + case NodeTypeBreak: + case NodeTypeContinue: + case NodeTypeUnreachable: + case NodeTypeDefer: + case NodeTypeSliceExpr: + case NodeTypeCatchExpr: + case NodeTypeContainerDecl: + case NodeTypeFnProto: + case NodeTypeErrorSetDecl: + case NodeTypeResume: + case NodeTypeAwaitExpr: + case NodeTypeSuspend: + case NodeTypeEnumLiteral: + case NodeTypeInferredArrayType: + case NodeTypeAnyTypeField: + case NodeTypePrefixOpExpr: + add_node_error(irb->codegen, node, + buf_sprintf("invalid left-hand side to assignment")); + return irb->codegen->invalid_inst_src; + + // @field can be assigned to + case NodeTypeFnCallExpr: + if (node->data.fn_call_expr.modifier == CallModifierBuiltin) { + AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr; + Buf *name = node_identifier_buf(fn_ref_expr); + auto entry = irb->codegen->builtin_fn_table.maybe_get(name); + + if (!entry) { + add_node_error(irb->codegen, node, + buf_sprintf("invalid builtin function: '%s'", buf_ptr(name))); + return irb->codegen->invalid_inst_src; + } + + if (entry->value->id == BuiltinFnIdField) { + break; + } + } + add_node_error(irb->codegen, node, + buf_sprintf("invalid left-hand side to assignment")); + return irb->codegen->invalid_inst_src; + + + // can be assigned to + case NodeTypeUnwrapOptional: + case NodeTypePtrDeref: + case NodeTypeFieldAccessExpr: + case NodeTypeArrayAccessExpr: + case NodeTypeIdentifier: + break; + } + } + if (result_loc == nullptr) { + // Create a result location indicating there is none - but if one gets created + // it will be properly distributed. + result_loc = no_result_loc(); + ir_build_reset_result(irb, scope, node, result_loc); + } + Scope *child_scope; + if (irb->exec->is_inline || + (irb->exec->fn_entry != nullptr && irb->exec->fn_entry->child_scope == scope)) + { + child_scope = scope; + } else { + child_scope = &create_expr_scope(irb->codegen, node, scope)->base; + } + IrInstSrc *result = ir_gen_node_raw(irb, node, child_scope, lval, result_loc); + if (result == irb->codegen->invalid_inst_src) { + if (irb->exec->first_err_trace_msg == nullptr) { + irb->exec->first_err_trace_msg = irb->codegen->trace_err; + } + } + return result; +} + +static IrInstSrc *ir_gen_node(IrBuilderSrc *irb, AstNode *node, Scope *scope) { + return ir_gen_node_extra(irb, node, scope, LValNone, nullptr); +} + +bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutableSrc *ir_executable) { + assert(node->owner); + + IrBuilderSrc ir_builder = {0}; + IrBuilderSrc *irb = &ir_builder; + + irb->codegen = codegen; + irb->exec = ir_executable; + irb->main_block_node = node; + + IrBasicBlockSrc *entry_block = ir_create_basic_block(irb, scope, "Entry"); + ir_set_cursor_at_end_and_append_block(irb, entry_block); + // Entry block gets a reference because we enter it to begin. + ir_ref_bb(irb->current_basic_block); + + IrInstSrc *result = ir_gen_node_extra(irb, node, scope, LValNone, nullptr); + + if (result == irb->codegen->invalid_inst_src) + return false; + + if (irb->exec->first_err_trace_msg != nullptr) { + codegen->trace_err = irb->exec->first_err_trace_msg; + return false; + } + + if (!instr_is_unreachable(result)) { + ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, result->base.source_node, result, nullptr)); + // no need for save_err_ret_addr because this cannot return error + ResultLocReturn *result_loc_ret = heap::c_allocator.create(); + result_loc_ret->base.id = ResultLocIdReturn; + ir_build_reset_result(irb, scope, node, &result_loc_ret->base); + ir_mark_gen(ir_build_end_expr(irb, scope, node, result, &result_loc_ret->base)); + ir_mark_gen(ir_build_return_src(irb, scope, result->base.source_node, result)); + } + + return true; +} + +bool ir_gen_fn(CodeGen *codegen, ZigFn *fn_entry) { + assert(fn_entry); + + IrExecutableSrc *ir_executable = fn_entry->ir_executable; + AstNode *body_node = fn_entry->body_node; + + assert(fn_entry->child_scope); + + return ir_gen(codegen, body_node, fn_entry->child_scope, ir_executable); +} + +void invalidate_exec(IrExecutableSrc *exec, ErrorMsg *msg) { + if (exec->first_err_trace_msg != nullptr) + return; + + exec->first_err_trace_msg = msg; + + for (size_t i = 0; i < exec->tld_list.length; i += 1) { + exec->tld_list.items[i]->resolution = TldResolutionInvalid; + } +} + +AstNode *ast_field_to_symbol_node(AstNode *err_set_field_node) { + if (err_set_field_node->type == NodeTypeIdentifier) { + return err_set_field_node; + } else if (err_set_field_node->type == NodeTypeErrorSetField) { + assert(err_set_field_node->data.err_set_field.field_name->type == NodeTypeIdentifier); + return err_set_field_node->data.err_set_field.field_name; + } else { + return err_set_field_node; + } +} + +void ir_add_call_stack_errors_gen(CodeGen *codegen, IrExecutableGen *exec, ErrorMsg *err_msg, int limit) { + if (!exec || !exec->source_node || limit < 0) return; + add_error_note(codegen, err_msg, exec->source_node, buf_sprintf("called from here")); + + ir_add_call_stack_errors_gen(codegen, exec->parent_exec, err_msg, limit - 1); +} + diff --git a/src/stage1/astgen.hpp b/src/stage1/astgen.hpp new file mode 100644 index 0000000000..c3750aac98 --- /dev/null +++ b/src/stage1/astgen.hpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2021 Andrew Kelley + * + * This file is part of zig, which is MIT licensed. + * See http://opensource.org/licenses/MIT + */ + +#ifndef ZIG_ASTGEN_HPP +#define ZIG_ASTGEN_HPP + +#include "all_types.hpp" + +bool ir_gen(CodeGen *g, AstNode *node, Scope *scope, IrExecutableSrc *ir_executable); +bool ir_gen_fn(CodeGen *g, ZigFn *fn_entry); + +bool ir_inst_src_has_side_effects(IrInstSrc *inst); + +ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_scope, + Buf *name, bool src_is_const, bool gen_is_const, bool is_shadowable, IrInstSrc *is_comptime, + bool skip_name_check); + +ResultLoc *no_result_loc(void); + +void invalidate_exec(IrExecutableSrc *exec, ErrorMsg *msg); + +AstNode *ast_field_to_symbol_node(AstNode *err_set_field_node); +void ir_add_call_stack_errors_gen(CodeGen *codegen, IrExecutableGen *exec, ErrorMsg *err_msg, + int limit); + +void destroy_instruction_src(IrInstSrc *inst); + +struct IrBuilderSrc { + CodeGen *codegen; + IrExecutableSrc *exec; + IrBasicBlockSrc *current_basic_block; + AstNode *main_block_node; +}; + +bool ir_should_inline(IrExecutableSrc *exec, Scope *scope); +Buf *get_anon_type_name(CodeGen *codegen, IrExecutableSrc *exec, const char *kind_name, + Scope *scope, AstNode *source_node, Buf *out_bare_name); + +#endif diff --git a/src/stage1/bigfloat.cpp b/src/stage1/bigfloat.cpp index 840cdccc8b..56bf2637e3 100644 --- a/src/stage1/bigfloat.cpp +++ b/src/stage1/bigfloat.cpp @@ -69,7 +69,7 @@ void bigfloat_init_bigint(BigFloat *dest, const BigInt *op) { } } -Error bigfloat_init_buf(BigFloat *dest, const uint8_t *buf_ptr, size_t buf_len) { +Error bigfloat_init_buf(BigFloat *dest, const uint8_t *buf_ptr) { char *str_begin = (char *)buf_ptr; char *str_end; @@ -79,7 +79,6 @@ Error bigfloat_init_buf(BigFloat *dest, const uint8_t *buf_ptr, size_t buf_len) return ErrorOverflow; } - assert(str_end <= ((char*)buf_ptr) + buf_len); return ErrorNone; } diff --git a/src/stage1/bigfloat.hpp b/src/stage1/bigfloat.hpp index 3ed6624fdc..52e92d20f4 100644 --- a/src/stage1/bigfloat.hpp +++ b/src/stage1/bigfloat.hpp @@ -28,7 +28,7 @@ void bigfloat_init_64(BigFloat *dest, double x); void bigfloat_init_128(BigFloat *dest, float128_t x); void bigfloat_init_bigfloat(BigFloat *dest, const BigFloat *x); void bigfloat_init_bigint(BigFloat *dest, const BigInt *op); -Error bigfloat_init_buf(BigFloat *dest, const uint8_t *buf_ptr, size_t buf_len); +Error bigfloat_init_buf(BigFloat *dest, const uint8_t *buf_ptr); float16_t bigfloat_to_f16(const BigFloat *bigfloat); float bigfloat_to_f32(const BigFloat *bigfloat); diff --git a/src/stage1/codegen.cpp b/src/stage1/codegen.cpp index 1a6f047ee1..1dd3aa8d45 100644 --- a/src/stage1/codegen.cpp +++ b/src/stage1/codegen.cpp @@ -6,7 +6,6 @@ */ #include "analyze.hpp" -#include "ast_render.hpp" #include "codegen.hpp" #include "errmsg.hpp" #include "error.hpp" @@ -642,6 +641,18 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn) { return fn->llvm_value; } +static uint32_t node_line_onebased(AstNode *node) { + RootStruct *root_struct = node->owner->data.structure.root_struct; + assert(node->main_token < root_struct->token_count); + return root_struct->token_locs[node->main_token].line + 1; +} + +static uint32_t node_column_onebased(AstNode *node) { + RootStruct *root_struct = node->owner->data.structure.root_struct; + assert(node->main_token < root_struct->token_count); + return root_struct->token_locs[node->main_token].column + 1; +} + static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) { if (scope->di_scope) return scope->di_scope; @@ -657,8 +668,7 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) { ZigFn *fn_table_entry = fn_scope->fn_entry; if (!fn_table_entry->proto_node) return get_di_scope(g, scope->parent); - unsigned line_number = (unsigned)(fn_table_entry->proto_node->line == 0) ? - 0 : (fn_table_entry->proto_node->line + 1); + unsigned line_number = node_line_onebased(fn_table_entry->proto_node); unsigned scope_line = line_number; bool is_definition = fn_table_entry->body_node != nullptr; bool is_optimized = g->build_mode != BuildModeDebug; @@ -696,8 +706,8 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) { ZigLLVMDILexicalBlock *di_block = ZigLLVMCreateLexicalBlock(g->dbuilder, get_di_scope(g, scope->parent), import->data.structure.root_struct->di_file, - (unsigned)scope->source_node->line + 1, - (unsigned)scope->source_node->column + 1); + node_line_onebased(scope->source_node), + node_column_onebased(scope->source_node)); scope->di_scope = ZigLLVMLexicalBlockToScope(di_block); return scope->di_scope; } @@ -1798,8 +1808,8 @@ static void gen_var_debug_decl(CodeGen *g, ZigVar *var) { if (g->strip_debug_symbols) return; assert(var->di_loc_var != nullptr); AstNode *source_node = var->decl_node; - ZigLLVMDILocation *debug_loc = ZigLLVMGetDebugLoc((unsigned)source_node->line + 1, - (unsigned)source_node->column + 1, get_di_scope(g, var->parent_scope)); + ZigLLVMDILocation *debug_loc = ZigLLVMGetDebugLoc(node_line_onebased(source_node), + node_column_onebased(source_node), get_di_scope(g, var->parent_scope)); ZigLLVMInsertDeclareAtEnd(g->dbuilder, var->value_ref, var->di_loc_var, debug_loc, LLVMGetInsertBlock(g->builder)); } @@ -2198,7 +2208,7 @@ var_ok: // arg index + 1 because the 0 index is return value var->di_loc_var = ZigLLVMCreateParameterVariable(g->dbuilder, get_di_scope(g, var->parent_scope), var->name, fn_walk->data.vars.import->data.structure.root_struct->di_file, - (unsigned)(var->decl_node->line + 1), + node_line_onebased(var->decl_node), get_llvm_di_type(g, dest_ty), !g->strip_debug_symbols, 0, di_arg_index + 1); } return true; @@ -4126,7 +4136,7 @@ static void render_async_spills(CodeGen *g) { if (var->decl_node) { var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope), var->name, import->data.structure.root_struct->di_file, - (unsigned)(var->decl_node->line + 1), + node_line_onebased(var->decl_node), get_llvm_di_type(g, var->var_type), !g->strip_debug_symbols, 0); gen_var_debug_decl(g, var); } @@ -6797,8 +6807,8 @@ static void set_debug_location(CodeGen *g, IrInstGen *instruction) { assert(source_node); assert(scope); - ZigLLVMSetCurrentDebugLocation(g->builder, (int)source_node->line + 1, - (int)source_node->column + 1, get_di_scope(g, scope)); + ZigLLVMSetCurrentDebugLocation(g->builder, node_line_onebased(source_node), + node_column_onebased(source_node), get_di_scope(g, scope)); } static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutableGen *executable, IrInstGen *instruction) { @@ -8021,7 +8031,7 @@ static void gen_global_var(CodeGen *g, ZigVar *var, LLVMValueRef init_val, bool is_local_to_unit = true; ZigLLVMCreateGlobalVariable(g->dbuilder, get_di_scope(g, var->parent_scope), var->name, var->name, import->data.structure.root_struct->di_file, - (unsigned)(var->decl_node->line + 1), + node_line_onebased(var->decl_node), get_llvm_di_type(g, type_entry), is_local_to_unit); // TODO ^^ make an actual global variable @@ -8296,7 +8306,8 @@ static void do_code_gen(CodeGen *g) { if (var->src_arg_index == SIZE_MAX) { var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope), - var->name, import->data.structure.root_struct->di_file, (unsigned)(var->decl_node->line + 1), + var->name, import->data.structure.root_struct->di_file, + node_line_onebased(var->decl_node), get_llvm_di_type(g, var->var_type), !g->strip_debug_symbols, 0); } else if (is_c_abi) { @@ -8321,7 +8332,7 @@ static void do_code_gen(CodeGen *g) { if (var->decl_node) { var->di_loc_var = ZigLLVMCreateParameterVariable(g->dbuilder, get_di_scope(g, var->parent_scope), var->name, import->data.structure.root_struct->di_file, - (unsigned)(var->decl_node->line + 1), + node_line_onebased(var->decl_node), get_llvm_di_type(g, gen_type), !g->strip_debug_symbols, 0, (unsigned)(gen_info->gen_index+1)); } @@ -8365,8 +8376,9 @@ static void do_code_gen(CodeGen *g) { if (!g->strip_debug_symbols) { AstNode *source_node = fn_table_entry->proto_node; - ZigLLVMSetCurrentDebugLocation(g->builder, (int)source_node->line + 1, - (int)source_node->column + 1, get_di_scope(g, fn_table_entry->child_scope)); + ZigLLVMSetCurrentDebugLocation(g->builder, + node_line_onebased(source_node), node_column_onebased(source_node), + get_di_scope(g, fn_table_entry->child_scope)); } IrExecutableGen *executable = &fn_table_entry->analyzed_executable; LLVMBasicBlockRef bad_resume_block = LLVMAppendBasicBlock(g->cur_fn_val, "BadResume"); diff --git a/src/stage1/dump_analysis.cpp b/src/stage1/dump_analysis.cpp index 69a797bdaf..15cd7c2874 100644 --- a/src/stage1/dump_analysis.cpp +++ b/src/stage1/dump_analysis.cpp @@ -1084,19 +1084,43 @@ static void anal_dump_type(AnalDumpCtx *ctx, ZigType *ty) { jw_end_object(jw); } +static Buf *collect_doc_comments(RootStruct *root_struct, TokenIndex first_token) { + if (first_token == 0) + return nullptr; + + TokenId *token_ids = root_struct->token_ids; + TokenLoc *token_locs = root_struct->token_locs; + Buf *str = buf_alloc(); + const char *source = buf_ptr(root_struct->source_code); + TokenIndex doc_token = first_token; + for (;token_ids[doc_token] == TokenIdDocComment; doc_token += 1) { + // chops off '///' but leaves '\n' + uint32_t start_pos = token_locs[doc_token].offset; + uint32_t token_len = 0; + while (source[start_pos + token_len] != '\n' && + source[start_pos + token_len] != 0) + { + token_len += 1; + } + buf_append_mem(str, source + start_pos + 3, token_len - 3); + } + return str; +} + static void anal_dump_node(AnalDumpCtx *ctx, const AstNode *node) { JsonWriter *jw = &ctx->jw; jw_begin_object(jw); jw_object_field(jw, "file"); - anal_dump_file_ref(ctx, node->owner->data.structure.root_struct->path); + RootStruct *root_struct = node->owner->data.structure.root_struct; + anal_dump_file_ref(ctx, root_struct->path); jw_object_field(jw, "line"); - jw_int(jw, node->line); + jw_int(jw, root_struct->token_locs[node->main_token].line); jw_object_field(jw, "col"); - jw_int(jw, node->column); + jw_int(jw, root_struct->token_locs[node->main_token].column); const Buf *doc_comments_buf = nullptr; const Buf *name_buf = nullptr; @@ -1107,30 +1131,30 @@ static void anal_dump_node(AnalDumpCtx *ctx, const AstNode *node) { switch (node->type) { case NodeTypeParamDecl: - doc_comments_buf = &node->data.param_decl.doc_comments; + doc_comments_buf = collect_doc_comments(root_struct, node->data.param_decl.doc_comments); name_buf = node->data.param_decl.name; is_var_args = node->data.param_decl.is_var_args; is_noalias = node->data.param_decl.is_noalias; is_comptime = node->data.param_decl.is_comptime; break; case NodeTypeFnProto: - doc_comments_buf = &node->data.fn_proto.doc_comments; + doc_comments_buf = collect_doc_comments(root_struct, node->data.fn_proto.doc_comments); field_nodes = &node->data.fn_proto.params; is_var_args = node->data.fn_proto.is_var_args; break; case NodeTypeVariableDeclaration: - doc_comments_buf = &node->data.variable_declaration.doc_comments; + doc_comments_buf = collect_doc_comments(root_struct, node->data.variable_declaration.doc_comments); break; case NodeTypeErrorSetField: - doc_comments_buf = &node->data.err_set_field.doc_comments; + doc_comments_buf = collect_doc_comments(root_struct, node->data.err_set_field.doc_comments); break; case NodeTypeStructField: - doc_comments_buf = &node->data.struct_field.doc_comments; + doc_comments_buf = collect_doc_comments(root_struct, node->data.struct_field.doc_comments); name_buf = node->data.struct_field.name; break; case NodeTypeContainerDecl: field_nodes = &node->data.container_decl.fields; - doc_comments_buf = &node->data.container_decl.doc_comments; + doc_comments_buf = collect_doc_comments(root_struct, node->data.container_decl.doc_comments); break; default: break; diff --git a/src/stage1/errmsg.cpp b/src/stage1/errmsg.cpp index 7bf096547f..e04d39fe88 100644 --- a/src/stage1/errmsg.cpp +++ b/src/stage1/errmsg.cpp @@ -96,14 +96,14 @@ void err_msg_add_note(ErrorMsg *parent, ErrorMsg *note) { parent->notes.append(note); } -ErrorMsg *err_msg_create_with_offset(Buf *path, size_t line, size_t column, size_t offset, - const char *source, Buf *msg) +ErrorMsg *err_msg_create_with_offset(Buf *path, uint32_t byte_offset, const char *source, + Buf *msg) { ErrorMsg *err_msg = heap::c_allocator.create(); err_msg->path = path; - err_msg->line_start = line; - err_msg->column_start = column; err_msg->msg = msg; + err_msg->line_start = 0; + err_msg->column_start = 0; if (source == nullptr) { // Must initialize the buffer anyway @@ -111,46 +111,25 @@ ErrorMsg *err_msg_create_with_offset(Buf *path, size_t line, size_t column, size return err_msg; } - size_t line_start_offset = offset; - for (;;) { - if (line_start_offset == 0) { - break; - } - - line_start_offset -= 1; - - if (source[line_start_offset] == '\n') { - line_start_offset += 1; - break; + size_t line_start = 0; + size_t i = 0; + for (;i < byte_offset; i += 1) { + switch (source[i]) { + case '\n': + err_msg->line_start += 1; + err_msg->column_start = 0; + line_start = i + 1; + continue; + default: + err_msg->column_start += 1; + continue; } } - - size_t line_end_offset = offset; - while (source[line_end_offset] && source[line_end_offset] != '\n') { - line_end_offset += 1; + while (source[i] != '\n' && source[i] != 0) { + i += 1; } - buf_init_from_mem(&err_msg->line_buf, source + line_start_offset, line_end_offset - line_start_offset); - - return err_msg; -} - -ErrorMsg *err_msg_create_with_line(Buf *path, size_t line, size_t column, - Buf *source, ZigList *line_offsets, Buf *msg) -{ - ErrorMsg *err_msg = heap::c_allocator.create(); - err_msg->path = path; - err_msg->line_start = line; - err_msg->column_start = column; - err_msg->msg = msg; - - size_t line_start_offset = line_offsets->at(line); - size_t end_line = line + 1; - size_t line_end_offset = (end_line >= line_offsets->length) ? buf_len(source) : line_offsets->at(line + 1); - size_t len = (line_end_offset + 1 > line_start_offset) ? (line_end_offset - line_start_offset - 1) : 0; - if (len == SIZE_MAX) len = 0; - - buf_init_from_mem(&err_msg->line_buf, buf_ptr(source) + line_start_offset, len); + buf_init_from_mem(&err_msg->line_buf, source + line_start, i - line_start); return err_msg; } diff --git a/src/stage1/errmsg.hpp b/src/stage1/errmsg.hpp index 73cbd4e0d9..b8b6b3e7f2 100644 --- a/src/stage1/errmsg.hpp +++ b/src/stage1/errmsg.hpp @@ -25,10 +25,6 @@ struct ErrorMsg { void print_err_msg(ErrorMsg *msg, ErrColor color); void err_msg_add_note(ErrorMsg *parent, ErrorMsg *note); -ErrorMsg *err_msg_create_with_offset(Buf *path, size_t line, size_t column, size_t offset, - const char *source, Buf *msg); - -ErrorMsg *err_msg_create_with_line(Buf *path, size_t line, size_t column, - Buf *source, ZigList *line_offsets, Buf *msg); +ErrorMsg *err_msg_create_with_offset(Buf *path, uint32_t byte_offset, const char *source, Buf *msg); #endif diff --git a/src/stage1/error.cpp b/src/stage1/error.cpp index d8bb4ac8a2..e77632e8f2 100644 --- a/src/stage1/error.cpp +++ b/src/stage1/error.cpp @@ -88,6 +88,8 @@ const char *err_str(Error err) { case ErrorZigIsTheCCompiler: return "Zig was not provided with libc installation information, and so it does not know where the libc paths are on the system. Zig attempted to use the system C compiler to find out where the libc paths are, but discovered that Zig is being used as the system C compiler."; case ErrorFileBusy: return "file is busy"; case ErrorLocked: return "file is locked by another process"; + case ErrorInvalidCharacter: return "invalid character"; + case ErrorUnicodePointTooLarge: return "unicode codepoint too large"; } return "(invalid error)"; } diff --git a/src/stage1/ir.cpp b/src/stage1/ir.cpp index 4bd608a687..4070372a12 100644 --- a/src/stage1/ir.cpp +++ b/src/stage1/ir.cpp @@ -5,8 +5,8 @@ * See http://opensource.org/licenses/MIT */ +#include "astgen.hpp" #include "analyze.hpp" -#include "ast_render.hpp" #include "error.hpp" #include "ir.hpp" #include "ir_print.hpp" @@ -22,13 +22,6 @@ #include #include -struct IrBuilderSrc { - CodeGen *codegen; - IrExecutableSrc *exec; - IrBasicBlockSrc *current_basic_block; - AstNode *main_block_node; -}; - struct IrBuilderGen { CodeGen *codegen; IrExecutableGen *exec; @@ -216,27 +209,18 @@ struct DbgIrBreakPoint { const char *src_file; uint32_t line; }; -DbgIrBreakPoint dbg_ir_breakpoints_buf[20]; -size_t dbg_ir_breakpoints_count = 0; -static IrInstSrc *ir_gen_node(IrBuilderSrc *irb, AstNode *node, Scope *scope); -static IrInstSrc *ir_gen_node_extra(IrBuilderSrc *irb, AstNode *node, Scope *scope, LVal lval, - ResultLoc *result_loc); static IrInstGen *ir_implicit_cast(IrAnalyze *ira, IrInstGen *value, ZigType *expected_type); static IrInstGen *ir_implicit_cast2(IrAnalyze *ira, IrInst *value_source_instr, IrInstGen *value, ZigType *expected_type); static IrInstGen *ir_get_deref(IrAnalyze *ira, IrInst *source_instr, IrInstGen *ptr, ResultLoc *result_loc); -static ErrorMsg *exec_add_error_node(CodeGen *codegen, IrExecutableSrc *exec, AstNode *source_node, Buf *msg); static IrInstGen *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name, IrInst* source_instr, IrInstGen *container_ptr, IrInst *container_ptr_src, ZigType *container_type, bool initializing); -static void ir_assert_impl(bool ok, IrInst* source_instruction, const char *file, unsigned int line); static void ir_assert_gen_impl(bool ok, IrInstGen *source_instruction, const char *file, unsigned int line); static IrInstGen *ir_get_var_ptr(IrAnalyze *ira, IrInst *source_instr, ZigVar *var); static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstGen *op); -static IrInstSrc *ir_lval_wrap(IrBuilderSrc *irb, Scope *scope, IrInstSrc *value, LVal lval, ResultLoc *result_loc); -static IrInstSrc *ir_expr_wrap(IrBuilderSrc *irb, Scope *scope, IrInstSrc *inst, ResultLoc *result_loc); static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_align); static ZigType *adjust_ptr_const(CodeGen *g, ZigType *ptr_type, bool is_const); static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align); @@ -265,26 +249,14 @@ static IrInstGen *ir_analyze_unwrap_err_code(IrAnalyze *ira, IrInst* source_inst IrInstGen *base_ptr, bool initializing); static IrInstGen *ir_analyze_store_ptr(IrAnalyze *ira, IrInst* source_instr, IrInstGen *ptr, IrInstGen *uncasted_value, bool allow_write_through_const); -static IrInstSrc *ir_gen_union_init_expr(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *union_type, IrInstSrc *field_name, AstNode *expr_node, - LVal lval, ResultLoc *parent_result_loc); static void ir_reset_result(ResultLoc *result_loc); -static Buf *get_anon_type_name(CodeGen *codegen, IrExecutableSrc *exec, const char *kind_name, - Scope *scope, AstNode *source_node, Buf *out_bare_name); -static ResultLocCast *ir_build_cast_result_loc(IrBuilderSrc *irb, IrInstSrc *dest_type, - ResultLoc *parent_result_loc); static IrInstGen *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInst* source_instr, TypeStructField *field, IrInstGen *struct_ptr, ZigType *struct_type, bool initializing); static IrInstGen *ir_analyze_inferred_field_ptr(IrAnalyze *ira, Buf *field_name, IrInst* source_instr, IrInstGen *container_ptr, ZigType *container_type); -static ResultLoc *no_result_loc(void); static IrInstGen *ir_analyze_test_non_null(IrAnalyze *ira, IrInst *source_inst, IrInstGen *value); static IrInstGen *ir_error_dependency_loop(IrAnalyze *ira, IrInst *source_instr); static IrInstGen *ir_const_undef(IrAnalyze *ira, IrInst *source_instruction, ZigType *ty); -static ZigVar *ir_create_var(IrBuilderSrc *irb, AstNode *node, Scope *scope, Buf *name, - bool src_is_const, bool gen_is_const, bool is_shadowable, IrInstSrc *is_comptime); -static void build_decl_var_and_init(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, ZigVar *var, - IrInstSrc *init, const char *name_hint, IrInstSrc *is_comptime); static IrInstGen *ir_analyze_union_init(IrAnalyze *ira, IrInst* source_instruction, AstNode *field_source_node, ZigType *union_type, Buf *field_name, IrInstGen *field_result_loc, IrInstGen *result_loc); @@ -295,292 +267,15 @@ static bool value_cmp_numeric_val_all(ZigValue *left, Cmp predicate, ZigValue *r static void memoize_field_init_val(CodeGen *codegen, ZigType *container_type, TypeStructField *field); static void value_to_bigfloat(BigFloat *out, ZigValue *val); +static void ir_assert_impl(bool ok, IrInst *source_instruction, char const *file, unsigned int line) { + if (ok) return; + src_assert_impl(ok, source_instruction->source_node, file, line); +} + + #define ir_assert(OK, SOURCE_INSTRUCTION) ir_assert_impl((OK), (SOURCE_INSTRUCTION), __FILE__, __LINE__) #define ir_assert_gen(OK, SOURCE_INSTRUCTION) ir_assert_gen_impl((OK), (SOURCE_INSTRUCTION), __FILE__, __LINE__) -static void destroy_instruction_src(IrInstSrc *inst) { - switch (inst->id) { - case IrInstSrcIdInvalid: - zig_unreachable(); - case IrInstSrcIdReturn: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdConst: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdBinOp: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdMergeErrSets: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdDeclVar: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdCall: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdCallExtra: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdAsyncCallExtra: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdUnOp: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdCondBr: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdBr: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdPhi: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdContainerInitList: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdContainerInitFields: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdUnreachable: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdElemPtr: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdVarPtr: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdLoadPtr: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdStorePtr: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdTypeOf: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdFieldPtr: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdSetCold: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdSetRuntimeSafety: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdSetFloatMode: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdArrayType: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdSliceType: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdAnyFrameType: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdAsm: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdSizeOf: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdTestNonNull: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdOptionalUnwrapPtr: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdPopCount: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdClz: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdCtz: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdBswap: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdBitReverse: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdSwitchBr: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdSwitchVar: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdSwitchElseVar: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdSwitchTarget: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdImport: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdRef: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdCompileErr: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdCompileLog: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdErrName: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdCImport: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdCInclude: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdCDefine: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdCUndef: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdEmbedFile: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdCmpxchg: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdFence: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdReduce: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdTruncate: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdIntCast: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdFloatCast: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdErrSetCast: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdIntToFloat: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdFloatToInt: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdBoolToInt: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdVectorType: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdShuffleVector: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdSplat: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdBoolNot: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdMemset: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdMemcpy: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdSlice: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdBreakpoint: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdReturnAddress: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdFrameAddress: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdFrameHandle: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdFrameType: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdFrameSize: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdAlignOf: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdOverflowOp: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdTestErr: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdUnwrapErrCode: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdUnwrapErrPayload: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdFnProto: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdTestComptime: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdPtrCast: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdBitCast: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdPtrToInt: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdIntToPtr: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdIntToEnum: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdIntToErr: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdErrToInt: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdCheckSwitchProngsUnderNo: - case IrInstSrcIdCheckSwitchProngsUnderYes: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdCheckStatementIsVoid: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdTypeName: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdTagName: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdPtrType: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdPtrTypeSimple: - case IrInstSrcIdPtrTypeSimpleConst: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdDeclRef: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdPanic: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdFieldParentPtr: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdByteOffsetOf: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdBitOffsetOf: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdTypeInfo: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdType: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdHasField: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdSetEvalBranchQuota: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdAlignCast: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdImplicitCast: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdResolveResult: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdResetResult: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdSetAlignStack: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdArgTypeAllowVarFalse: - case IrInstSrcIdArgTypeAllowVarTrue: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdExport: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdExtern: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdErrorReturnTrace: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdErrorUnion: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdAtomicRmw: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdSaveErrRetAddr: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdAddImplicitReturnType: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdFloatOp: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdMulAdd: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdAtomicLoad: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdAtomicStore: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdEnumToInt: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdCheckRuntimeScope: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdHasDecl: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdUndeclaredIdent: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdAlloca: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdEndExpr: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdUnionInitNamedField: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdSuspendBegin: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdSuspendFinish: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdResume: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdAwait: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdSpillBegin: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdSpillEnd: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdCallArgs: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdWasmMemorySize: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdWasmMemoryGrow: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdSrc: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - } - zig_unreachable(); -} - void destroy_instruction_gen(IrInstGen *inst) { switch (inst->id) { case IrInstGenIdInvalid: @@ -970,54 +665,18 @@ static bool types_have_same_zig_comptime_repr(CodeGen *codegen, ZigType *expecte zig_unreachable(); } -static bool ir_should_inline(IrExecutableSrc *exec, Scope *scope) { - if (exec->is_inline) - return true; - - while (scope != nullptr) { - if (scope->id == ScopeIdCompTime) - return true; - if (scope->id == ScopeIdTypeOf) - return false; - if (scope->id == ScopeIdFnDef) - break; - scope = scope->parent; - } - return false; -} - -static void ir_instruction_append(IrBasicBlockSrc *basic_block, IrInstSrc *instruction) { - assert(basic_block); - assert(instruction); - basic_block->instruction_list.append(instruction); -} - static void ir_inst_gen_append(IrBasicBlockGen *basic_block, IrInstGen *instruction) { assert(basic_block); assert(instruction); basic_block->instruction_list.append(instruction); } -static size_t exec_next_debug_id(IrExecutableSrc *exec) { - size_t result = exec->next_debug_id; - exec->next_debug_id += 1; - return result; -} - static size_t exec_next_debug_id_gen(IrExecutableGen *exec) { size_t result = exec->next_debug_id; exec->next_debug_id += 1; return result; } -static ZigFn *exec_fn_entry(IrExecutableSrc *exec) { - return exec->fn_entry; -} - -static Buf *exec_c_import_buf(IrExecutableSrc *exec) { - return exec->c_import_buf; -} - static bool value_is_comptime(ZigValue *const_val) { return const_val->special != ConstValSpecialRuntime; } @@ -1026,33 +685,11 @@ static bool instr_is_comptime(IrInstGen *instruction) { return value_is_comptime(instruction->value); } -static bool instr_is_unreachable(IrInstSrc *instruction) { - return instruction->is_noreturn; -} - -static void ir_ref_bb(IrBasicBlockSrc *bb) { - bb->ref_count += 1; -} - -static void ir_ref_instruction(IrInstSrc *instruction, IrBasicBlockSrc *cur_bb) { - assert(instruction->id != IrInstSrcIdInvalid); - instruction->base.ref_count += 1; - if (instruction->owner_bb != cur_bb && !instr_is_unreachable(instruction) - && instruction->id != IrInstSrcIdConst) - { - ir_ref_bb(instruction->owner_bb); - } -} - static void ir_ref_inst_gen(IrInstGen *instruction) { assert(instruction->id != IrInstGenIdInvalid); instruction->base.ref_count += 1; } -static void ir_ref_var(ZigVar *var) { - var->ref_count += 1; -} - static void create_result_ptr(CodeGen *codegen, ZigType *expected_type, ZigValue **out_result, ZigValue **out_result_ptr) { @@ -1092,15 +729,6 @@ ZigType *ir_analyze_type_expr(IrAnalyze *ira, Scope *scope, AstNode *node) { return res_type; } -static IrBasicBlockSrc *ir_create_basic_block(IrBuilderSrc *irb, Scope *scope, const char *name_hint) { - IrBasicBlockSrc *result = heap::c_allocator.create(); - result->scope = scope; - result->name_hint = name_hint; - result->debug_id = exec_next_debug_id(irb->exec); - result->index = UINT32_MAX; // set later - return result; -} - static IrBasicBlockGen *ir_create_basic_block_gen(IrAnalyze *ira, Scope *scope, const char *name_hint) { IrBasicBlockGen *result = heap::c_allocator.create(); result->scope = scope; @@ -1115,538 +743,6 @@ static IrBasicBlockGen *ir_build_bb_from(IrAnalyze *ira, IrBasicBlockSrc *other_ return new_bb; } -static constexpr IrInstSrcId ir_inst_id(IrInstSrcDeclVar *) { - return IrInstSrcIdDeclVar; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcBr *) { - return IrInstSrcIdBr; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcCondBr *) { - return IrInstSrcIdCondBr; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcSwitchBr *) { - return IrInstSrcIdSwitchBr; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcSwitchVar *) { - return IrInstSrcIdSwitchVar; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcSwitchElseVar *) { - return IrInstSrcIdSwitchElseVar; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcSwitchTarget *) { - return IrInstSrcIdSwitchTarget; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcPhi *) { - return IrInstSrcIdPhi; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcUnOp *) { - return IrInstSrcIdUnOp; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcBinOp *) { - return IrInstSrcIdBinOp; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcMergeErrSets *) { - return IrInstSrcIdMergeErrSets; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcLoadPtr *) { - return IrInstSrcIdLoadPtr; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcStorePtr *) { - return IrInstSrcIdStorePtr; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcFieldPtr *) { - return IrInstSrcIdFieldPtr; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcElemPtr *) { - return IrInstSrcIdElemPtr; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcVarPtr *) { - return IrInstSrcIdVarPtr; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcCall *) { - return IrInstSrcIdCall; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcCallArgs *) { - return IrInstSrcIdCallArgs; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcCallExtra *) { - return IrInstSrcIdCallExtra; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcAsyncCallExtra *) { - return IrInstSrcIdAsyncCallExtra; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcConst *) { - return IrInstSrcIdConst; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcReturn *) { - return IrInstSrcIdReturn; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcContainerInitList *) { - return IrInstSrcIdContainerInitList; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcContainerInitFields *) { - return IrInstSrcIdContainerInitFields; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcUnreachable *) { - return IrInstSrcIdUnreachable; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcTypeOf *) { - return IrInstSrcIdTypeOf; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcSetCold *) { - return IrInstSrcIdSetCold; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcSetRuntimeSafety *) { - return IrInstSrcIdSetRuntimeSafety; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcSetFloatMode *) { - return IrInstSrcIdSetFloatMode; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcArrayType *) { - return IrInstSrcIdArrayType; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcAnyFrameType *) { - return IrInstSrcIdAnyFrameType; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcSliceType *) { - return IrInstSrcIdSliceType; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcAsm *) { - return IrInstSrcIdAsm; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcSizeOf *) { - return IrInstSrcIdSizeOf; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcTestNonNull *) { - return IrInstSrcIdTestNonNull; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcOptionalUnwrapPtr *) { - return IrInstSrcIdOptionalUnwrapPtr; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcClz *) { - return IrInstSrcIdClz; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcCtz *) { - return IrInstSrcIdCtz; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcPopCount *) { - return IrInstSrcIdPopCount; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcBswap *) { - return IrInstSrcIdBswap; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcBitReverse *) { - return IrInstSrcIdBitReverse; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcImport *) { - return IrInstSrcIdImport; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcCImport *) { - return IrInstSrcIdCImport; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcCInclude *) { - return IrInstSrcIdCInclude; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcCDefine *) { - return IrInstSrcIdCDefine; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcCUndef *) { - return IrInstSrcIdCUndef; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcRef *) { - return IrInstSrcIdRef; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcCompileErr *) { - return IrInstSrcIdCompileErr; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcCompileLog *) { - return IrInstSrcIdCompileLog; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcErrName *) { - return IrInstSrcIdErrName; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcEmbedFile *) { - return IrInstSrcIdEmbedFile; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcCmpxchg *) { - return IrInstSrcIdCmpxchg; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcFence *) { - return IrInstSrcIdFence; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcReduce *) { - return IrInstSrcIdReduce; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcTruncate *) { - return IrInstSrcIdTruncate; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcIntCast *) { - return IrInstSrcIdIntCast; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcFloatCast *) { - return IrInstSrcIdFloatCast; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcIntToFloat *) { - return IrInstSrcIdIntToFloat; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcFloatToInt *) { - return IrInstSrcIdFloatToInt; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcBoolToInt *) { - return IrInstSrcIdBoolToInt; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcVectorType *) { - return IrInstSrcIdVectorType; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcShuffleVector *) { - return IrInstSrcIdShuffleVector; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcSplat *) { - return IrInstSrcIdSplat; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcBoolNot *) { - return IrInstSrcIdBoolNot; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcMemset *) { - return IrInstSrcIdMemset; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcMemcpy *) { - return IrInstSrcIdMemcpy; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcSlice *) { - return IrInstSrcIdSlice; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcBreakpoint *) { - return IrInstSrcIdBreakpoint; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcReturnAddress *) { - return IrInstSrcIdReturnAddress; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcFrameAddress *) { - return IrInstSrcIdFrameAddress; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcFrameHandle *) { - return IrInstSrcIdFrameHandle; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcFrameType *) { - return IrInstSrcIdFrameType; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcFrameSize *) { - return IrInstSrcIdFrameSize; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcAlignOf *) { - return IrInstSrcIdAlignOf; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcOverflowOp *) { - return IrInstSrcIdOverflowOp; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcTestErr *) { - return IrInstSrcIdTestErr; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcMulAdd *) { - return IrInstSrcIdMulAdd; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcFloatOp *) { - return IrInstSrcIdFloatOp; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcUnwrapErrCode *) { - return IrInstSrcIdUnwrapErrCode; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcUnwrapErrPayload *) { - return IrInstSrcIdUnwrapErrPayload; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcFnProto *) { - return IrInstSrcIdFnProto; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcTestComptime *) { - return IrInstSrcIdTestComptime; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcPtrCast *) { - return IrInstSrcIdPtrCast; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcBitCast *) { - return IrInstSrcIdBitCast; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcIntToPtr *) { - return IrInstSrcIdIntToPtr; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcPtrToInt *) { - return IrInstSrcIdPtrToInt; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcIntToEnum *) { - return IrInstSrcIdIntToEnum; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcEnumToInt *) { - return IrInstSrcIdEnumToInt; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcIntToErr *) { - return IrInstSrcIdIntToErr; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcErrToInt *) { - return IrInstSrcIdErrToInt; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcCheckStatementIsVoid *) { - return IrInstSrcIdCheckStatementIsVoid; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcTypeName *) { - return IrInstSrcIdTypeName; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcDeclRef *) { - return IrInstSrcIdDeclRef; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcPanic *) { - return IrInstSrcIdPanic; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcTagName *) { - return IrInstSrcIdTagName; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcFieldParentPtr *) { - return IrInstSrcIdFieldParentPtr; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcByteOffsetOf *) { - return IrInstSrcIdByteOffsetOf; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcBitOffsetOf *) { - return IrInstSrcIdBitOffsetOf; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcTypeInfo *) { - return IrInstSrcIdTypeInfo; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcType *) { - return IrInstSrcIdType; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcHasField *) { - return IrInstSrcIdHasField; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcSetEvalBranchQuota *) { - return IrInstSrcIdSetEvalBranchQuota; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcPtrType *) { - return IrInstSrcIdPtrType; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcAlignCast *) { - return IrInstSrcIdAlignCast; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcImplicitCast *) { - return IrInstSrcIdImplicitCast; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcResolveResult *) { - return IrInstSrcIdResolveResult; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcResetResult *) { - return IrInstSrcIdResetResult; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcSetAlignStack *) { - return IrInstSrcIdSetAlignStack; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcExport *) { - return IrInstSrcIdExport; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcExtern *) { - return IrInstSrcIdExtern; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcErrorReturnTrace *) { - return IrInstSrcIdErrorReturnTrace; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcErrorUnion *) { - return IrInstSrcIdErrorUnion; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcAtomicRmw *) { - return IrInstSrcIdAtomicRmw; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcAtomicLoad *) { - return IrInstSrcIdAtomicLoad; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcAtomicStore *) { - return IrInstSrcIdAtomicStore; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcSaveErrRetAddr *) { - return IrInstSrcIdSaveErrRetAddr; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcAddImplicitReturnType *) { - return IrInstSrcIdAddImplicitReturnType; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcErrSetCast *) { - return IrInstSrcIdErrSetCast; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcCheckRuntimeScope *) { - return IrInstSrcIdCheckRuntimeScope; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcHasDecl *) { - return IrInstSrcIdHasDecl; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcUndeclaredIdent *) { - return IrInstSrcIdUndeclaredIdent; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcAlloca *) { - return IrInstSrcIdAlloca; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcEndExpr *) { - return IrInstSrcIdEndExpr; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcUnionInitNamedField *) { - return IrInstSrcIdUnionInitNamedField; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcSuspendBegin *) { - return IrInstSrcIdSuspendBegin; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcSuspendFinish *) { - return IrInstSrcIdSuspendFinish; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcAwait *) { - return IrInstSrcIdAwait; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcResume *) { - return IrInstSrcIdResume; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcSpillBegin *) { - return IrInstSrcIdSpillBegin; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcSpillEnd *) { - return IrInstSrcIdSpillEnd; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcWasmMemorySize *) { - return IrInstSrcIdWasmMemorySize; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcWasmMemoryGrow *) { - return IrInstSrcIdWasmMemoryGrow; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcSrc *) { - return IrInstSrcIdSrc; -} - static constexpr IrInstGenId ir_inst_id(IrInstGenDeclVar *) { return IrInstGenIdDeclVar; } @@ -2003,17 +1099,6 @@ static constexpr IrInstGenId ir_inst_id(IrInstGenExtern *) { return IrInstGenIdExtern; } -template -static T *ir_create_instruction(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { - T *special_instruction = heap::c_allocator.create(); - special_instruction->base.id = ir_inst_id(special_instruction); - special_instruction->base.base.scope = scope; - special_instruction->base.base.source_node = source_node; - special_instruction->base.base.debug_id = exec_next_debug_id(irb->exec); - special_instruction->base.owner_bb = irb->current_basic_block; - return special_instruction; -} - template static T *ir_create_inst_gen(IrBuilderGen *irb, Scope *scope, AstNode *source_node) { T *special_instruction = heap::c_allocator.create(); @@ -2037,13 +1122,6 @@ static T *ir_create_inst_noval(IrBuilderGen *irb, Scope *scope, AstNode *source_ return special_instruction; } -template -static T *ir_build_instruction(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { - T *special_instruction = ir_create_instruction(irb, scope, source_node); - ir_instruction_append(irb->current_basic_block, &special_instruction->base); - return special_instruction; -} - template static T *ir_build_inst_gen(IrBuilderGen *irb, Scope *scope, AstNode *source_node) { T *special_instruction = ir_create_inst_gen(irb, scope, source_node); @@ -2095,24 +1173,6 @@ static IrInstGen *ir_build_cast(IrAnalyze *ira, IrInst *source_instr,ZigType *de return &inst->base; } -static IrInstSrc *ir_build_cond_br(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *condition, - IrBasicBlockSrc *then_block, IrBasicBlockSrc *else_block, IrInstSrc *is_comptime) -{ - IrInstSrcCondBr *inst = ir_build_instruction(irb, scope, source_node); - inst->base.is_noreturn = true; - inst->condition = condition; - inst->then_block = then_block; - inst->else_block = else_block; - inst->is_comptime = is_comptime; - - ir_ref_instruction(condition, irb->current_basic_block); - ir_ref_bb(then_block); - ir_ref_bb(else_block); - if (is_comptime != nullptr) ir_ref_instruction(is_comptime, irb->current_basic_block); - - return &inst->base; -} - static IrInstGen *ir_build_cond_br_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *condition, IrBasicBlockGen *then_block, IrBasicBlockGen *else_block) { @@ -2126,16 +1186,6 @@ static IrInstGen *ir_build_cond_br_gen(IrAnalyze *ira, IrInst *source_instr, IrI return &inst->base; } -static IrInstSrc *ir_build_return_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *operand) { - IrInstSrcReturn *inst = ir_build_instruction(irb, scope, source_node); - inst->base.is_noreturn = true; - inst->operand = operand; - - if (operand != nullptr) ir_ref_instruction(operand, irb->current_basic_block); - - return &inst->base; -} - static IrInstGen *ir_build_return_gen(IrAnalyze *ira, IrInst *source_inst, IrInstGen *operand) { IrInstGenReturn *inst = ir_build_inst_noreturn(&ira->new_irb, source_inst->scope, source_inst->source_node); @@ -2146,139 +1196,6 @@ static IrInstGen *ir_build_return_gen(IrAnalyze *ira, IrInst *source_inst, IrIns return &inst->base; } -static IrInstSrc *ir_build_const_void(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { - IrInstSrcConst *const_instruction = ir_create_instruction(irb, scope, source_node); - ir_instruction_append(irb->current_basic_block, &const_instruction->base); - const_instruction->value = irb->codegen->intern.for_void(); - return &const_instruction->base; -} - -static IrInstSrc *ir_build_const_undefined(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { - IrInstSrcConst *const_instruction = ir_create_instruction(irb, scope, source_node); - ir_instruction_append(irb->current_basic_block, &const_instruction->base); - const_instruction->value = irb->codegen->intern.for_undefined(); - const_instruction->value->special = ConstValSpecialUndef; - return &const_instruction->base; -} - -static IrInstSrc *ir_build_const_uint(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, uint64_t value) { - IrInstSrcConst *const_instruction = ir_build_instruction(irb, scope, source_node); - const_instruction->value = irb->codegen->pass1_arena->create(); - const_instruction->value->type = irb->codegen->builtin_types.entry_num_lit_int; - const_instruction->value->special = ConstValSpecialStatic; - bigint_init_unsigned(&const_instruction->value->data.x_bigint, value); - return &const_instruction->base; -} - -static IrInstSrc *ir_build_const_bigint(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, BigInt *bigint) { - IrInstSrcConst *const_instruction = ir_build_instruction(irb, scope, source_node); - const_instruction->value = irb->codegen->pass1_arena->create(); - const_instruction->value->type = irb->codegen->builtin_types.entry_num_lit_int; - const_instruction->value->special = ConstValSpecialStatic; - bigint_init_bigint(&const_instruction->value->data.x_bigint, bigint); - return &const_instruction->base; -} - -static IrInstSrc *ir_build_const_bigfloat(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, BigFloat *bigfloat) { - IrInstSrcConst *const_instruction = ir_build_instruction(irb, scope, source_node); - const_instruction->value = irb->codegen->pass1_arena->create(); - const_instruction->value->type = irb->codegen->builtin_types.entry_num_lit_float; - const_instruction->value->special = ConstValSpecialStatic; - bigfloat_init_bigfloat(&const_instruction->value->data.x_bigfloat, bigfloat); - return &const_instruction->base; -} - -static IrInstSrc *ir_build_const_null(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { - IrInstSrcConst *const_instruction = ir_create_instruction(irb, scope, source_node); - ir_instruction_append(irb->current_basic_block, &const_instruction->base); - const_instruction->value = irb->codegen->intern.for_null(); - return &const_instruction->base; -} - -static IrInstSrc *ir_build_const_usize(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, uint64_t value) { - IrInstSrcConst *const_instruction = ir_build_instruction(irb, scope, source_node); - const_instruction->value = irb->codegen->pass1_arena->create(); - const_instruction->value->type = irb->codegen->builtin_types.entry_usize; - const_instruction->value->special = ConstValSpecialStatic; - bigint_init_unsigned(&const_instruction->value->data.x_bigint, value); - return &const_instruction->base; -} - -static IrInstSrc *ir_create_const_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - ZigType *type_entry) -{ - IrInstSrcConst *const_instruction = ir_create_instruction(irb, scope, source_node); - const_instruction->value = irb->codegen->pass1_arena->create(); - const_instruction->value->type = irb->codegen->builtin_types.entry_type; - const_instruction->value->special = ConstValSpecialStatic; - const_instruction->value->data.x_type = type_entry; - return &const_instruction->base; -} - -static IrInstSrc *ir_build_const_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - ZigType *type_entry) -{ - IrInstSrc *instruction = ir_create_const_type(irb, scope, source_node, type_entry); - ir_instruction_append(irb->current_basic_block, instruction); - return instruction; -} - -static IrInstSrc *ir_build_const_import(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, ZigType *import) { - IrInstSrcConst *const_instruction = ir_build_instruction(irb, scope, source_node); - const_instruction->value = irb->codegen->pass1_arena->create(); - const_instruction->value->type = irb->codegen->builtin_types.entry_type; - const_instruction->value->special = ConstValSpecialStatic; - const_instruction->value->data.x_type = import; - return &const_instruction->base; -} - -static IrInstSrc *ir_build_const_bool(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, bool value) { - IrInstSrcConst *const_instruction = ir_build_instruction(irb, scope, source_node); - const_instruction->value = irb->codegen->pass1_arena->create(); - const_instruction->value->type = irb->codegen->builtin_types.entry_bool; - const_instruction->value->special = ConstValSpecialStatic; - const_instruction->value->data.x_bool = value; - return &const_instruction->base; -} - -static IrInstSrc *ir_build_const_enum_literal(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, Buf *name) { - IrInstSrcConst *const_instruction = ir_build_instruction(irb, scope, source_node); - const_instruction->value = irb->codegen->pass1_arena->create(); - const_instruction->value->type = irb->codegen->builtin_types.entry_enum_literal; - const_instruction->value->special = ConstValSpecialStatic; - const_instruction->value->data.x_enum_literal = name; - return &const_instruction->base; -} - -static IrInstSrc *ir_create_const_str_lit(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, Buf *str) { - IrInstSrcConst *const_instruction = ir_create_instruction(irb, scope, source_node); - const_instruction->value = irb->codegen->pass1_arena->create(); - init_const_str_lit(irb->codegen, const_instruction->value, str); - - return &const_instruction->base; -} - -static IrInstSrc *ir_build_const_str_lit(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, Buf *str) { - IrInstSrc *instruction = ir_create_const_str_lit(irb, scope, source_node, str); - ir_instruction_append(irb->current_basic_block, instruction); - return instruction; -} - -static IrInstSrc *ir_build_bin_op(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrBinOp op_id, - IrInstSrc *op1, IrInstSrc *op2, bool safety_check_on) -{ - IrInstSrcBinOp *inst = ir_build_instruction(irb, scope, source_node); - inst->op_id = op_id; - inst->op1 = op1; - inst->op2 = op2; - inst->safety_check_on = safety_check_on; - - ir_ref_instruction(op1, irb->current_basic_block); - ir_ref_instruction(op2, irb->current_basic_block); - - return &inst->base; -} - static IrInstGen *ir_build_bin_op_gen(IrAnalyze *ira, IrInst *source_instr, ZigType *res_type, IrBinOp op_id, IrInstGen *op1, IrInstGen *op2, bool safety_check_on) { @@ -2297,41 +1214,11 @@ static IrInstGen *ir_build_bin_op_gen(IrAnalyze *ira, IrInst *source_instr, ZigT } -static IrInstSrc *ir_build_merge_err_sets(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *op1, IrInstSrc *op2, Buf *type_name) -{ - IrInstSrcMergeErrSets *inst = ir_build_instruction(irb, scope, source_node); - inst->op1 = op1; - inst->op2 = op2; - inst->type_name = type_name; - - ir_ref_instruction(op1, irb->current_basic_block); - ir_ref_instruction(op2, irb->current_basic_block); - - return &inst->base; -} - -static IrInstSrc *ir_build_var_ptr_x(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, ZigVar *var, - ScopeFnDef *crossed_fndef_scope) -{ - IrInstSrcVarPtr *instruction = ir_build_instruction(irb, scope, source_node); - instruction->var = var; - instruction->crossed_fndef_scope = crossed_fndef_scope; - - ir_ref_var(var); - - return &instruction->base; -} - -static IrInstSrc *ir_build_var_ptr(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, ZigVar *var) { - return ir_build_var_ptr_x(irb, scope, source_node, var, nullptr); -} - static IrInstGen *ir_build_var_ptr_gen(IrAnalyze *ira, IrInst *source_instr, ZigVar *var) { IrInstGenVarPtr *instruction = ir_build_inst_gen(&ira->new_irb, source_instr->scope, source_instr->source_node); instruction->var = var; - ir_ref_var(var); + var->ref_count += 1; return &instruction->base; } @@ -2342,23 +1229,6 @@ static IrInstGen *ir_build_return_ptr(IrAnalyze *ira, Scope *scope, AstNode *sou return &instruction->base; } -static IrInstSrc *ir_build_elem_ptr(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *array_ptr, IrInstSrc *elem_index, bool safety_check_on, PtrLen ptr_len, - AstNode *init_array_type_source_node) -{ - IrInstSrcElemPtr *instruction = ir_build_instruction(irb, scope, source_node); - instruction->array_ptr = array_ptr; - instruction->elem_index = elem_index; - instruction->safety_check_on = safety_check_on; - instruction->ptr_len = ptr_len; - instruction->init_array_type_source_node = init_array_type_source_node; - - ir_ref_instruction(array_ptr, irb->current_basic_block); - ir_ref_instruction(elem_index, irb->current_basic_block); - - return &instruction->base; -} - static IrInstGen *ir_build_elem_ptr_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, IrInstGen *array_ptr, IrInstGen *elem_index, bool safety_check_on, ZigType *return_type) { @@ -2374,48 +1244,6 @@ static IrInstGen *ir_build_elem_ptr_gen(IrAnalyze *ira, Scope *scope, AstNode *s return &instruction->base; } -static IrInstSrc *ir_build_field_ptr_instruction(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *container_ptr, IrInstSrc *field_name_expr, bool initializing) -{ - IrInstSrcFieldPtr *instruction = ir_build_instruction(irb, scope, source_node); - instruction->container_ptr = container_ptr; - instruction->field_name_buffer = nullptr; - instruction->field_name_expr = field_name_expr; - instruction->initializing = initializing; - - ir_ref_instruction(container_ptr, irb->current_basic_block); - ir_ref_instruction(field_name_expr, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstSrc *ir_build_field_ptr(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *container_ptr, Buf *field_name, bool initializing) -{ - IrInstSrcFieldPtr *instruction = ir_build_instruction(irb, scope, source_node); - instruction->container_ptr = container_ptr; - instruction->field_name_buffer = field_name; - instruction->field_name_expr = nullptr; - instruction->initializing = initializing; - - ir_ref_instruction(container_ptr, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstSrc *ir_build_has_field(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *container_type, IrInstSrc *field_name) -{ - IrInstSrcHasField *instruction = ir_build_instruction(irb, scope, source_node); - instruction->container_type = container_type; - instruction->field_name = field_name; - - ir_ref_instruction(container_type, irb->current_basic_block); - ir_ref_instruction(field_name, irb->current_basic_block); - - return &instruction->base; -} - static IrInstGen *ir_build_struct_field_ptr(IrAnalyze *ira, IrInst *source_instr, IrInstGen *struct_ptr, TypeStructField *field, ZigType *ptr_type) { @@ -2445,85 +1273,6 @@ static IrInstGen *ir_build_union_field_ptr(IrAnalyze *ira, IrInst *source_instr, return &inst->base; } -static IrInstSrc *ir_build_call_extra(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *options, IrInstSrc *fn_ref, IrInstSrc *args, ResultLoc *result_loc) -{ - IrInstSrcCallExtra *call_instruction = ir_build_instruction(irb, scope, source_node); - call_instruction->options = options; - call_instruction->fn_ref = fn_ref; - call_instruction->args = args; - call_instruction->result_loc = result_loc; - - ir_ref_instruction(options, irb->current_basic_block); - ir_ref_instruction(fn_ref, irb->current_basic_block); - ir_ref_instruction(args, irb->current_basic_block); - - return &call_instruction->base; -} - -static IrInstSrc *ir_build_async_call_extra(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - CallModifier modifier, IrInstSrc *fn_ref, IrInstSrc *ret_ptr, IrInstSrc *new_stack, IrInstSrc *args, ResultLoc *result_loc) -{ - IrInstSrcAsyncCallExtra *call_instruction = ir_build_instruction(irb, scope, source_node); - call_instruction->modifier = modifier; - call_instruction->fn_ref = fn_ref; - call_instruction->ret_ptr = ret_ptr; - call_instruction->new_stack = new_stack; - call_instruction->args = args; - call_instruction->result_loc = result_loc; - - ir_ref_instruction(fn_ref, irb->current_basic_block); - if (ret_ptr != nullptr) ir_ref_instruction(ret_ptr, irb->current_basic_block); - ir_ref_instruction(new_stack, irb->current_basic_block); - ir_ref_instruction(args, irb->current_basic_block); - - return &call_instruction->base; -} - -static IrInstSrc *ir_build_call_args(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *options, IrInstSrc *fn_ref, IrInstSrc **args_ptr, size_t args_len, - ResultLoc *result_loc) -{ - IrInstSrcCallArgs *call_instruction = ir_build_instruction(irb, scope, source_node); - call_instruction->options = options; - call_instruction->fn_ref = fn_ref; - call_instruction->args_ptr = args_ptr; - call_instruction->args_len = args_len; - call_instruction->result_loc = result_loc; - - ir_ref_instruction(options, irb->current_basic_block); - ir_ref_instruction(fn_ref, irb->current_basic_block); - for (size_t i = 0; i < args_len; i += 1) - ir_ref_instruction(args_ptr[i], irb->current_basic_block); - - return &call_instruction->base; -} - -static IrInstSrc *ir_build_call_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - ZigFn *fn_entry, IrInstSrc *fn_ref, size_t arg_count, IrInstSrc **args, - IrInstSrc *ret_ptr, CallModifier modifier, bool is_async_call_builtin, - IrInstSrc *new_stack, ResultLoc *result_loc) -{ - IrInstSrcCall *call_instruction = ir_build_instruction(irb, scope, source_node); - call_instruction->fn_entry = fn_entry; - call_instruction->fn_ref = fn_ref; - call_instruction->args = args; - call_instruction->arg_count = arg_count; - call_instruction->modifier = modifier; - call_instruction->is_async_call_builtin = is_async_call_builtin; - call_instruction->new_stack = new_stack; - call_instruction->result_loc = result_loc; - call_instruction->ret_ptr = ret_ptr; - - if (fn_ref != nullptr) ir_ref_instruction(fn_ref, irb->current_basic_block); - for (size_t i = 0; i < arg_count; i += 1) - ir_ref_instruction(args[i], irb->current_basic_block); - if (ret_ptr != nullptr) ir_ref_instruction(ret_ptr, irb->current_basic_block); - if (new_stack != nullptr) ir_ref_instruction(new_stack, irb->current_basic_block); - - return &call_instruction->base; -} - static IrInstGenCall *ir_build_call_gen(IrAnalyze *ira, IrInst *source_instruction, ZigFn *fn_entry, IrInstGen *fn_ref, size_t arg_count, IrInstGen **args, CallModifier modifier, IrInstGen *new_stack, bool is_async_call_builtin, @@ -2550,27 +1299,6 @@ static IrInstGenCall *ir_build_call_gen(IrAnalyze *ira, IrInst *source_instructi return call_instruction; } -static IrInstSrc *ir_build_phi(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - size_t incoming_count, IrBasicBlockSrc **incoming_blocks, IrInstSrc **incoming_values, - ResultLocPeerParent *peer_parent) -{ - assert(incoming_count != 0); - assert(incoming_count != SIZE_MAX); - - IrInstSrcPhi *phi_instruction = ir_build_instruction(irb, scope, source_node); - phi_instruction->incoming_count = incoming_count; - phi_instruction->incoming_blocks = incoming_blocks; - phi_instruction->incoming_values = incoming_values; - phi_instruction->peer_parent = peer_parent; - - for (size_t i = 0; i < incoming_count; i += 1) { - ir_ref_bb(incoming_blocks[i]); - ir_ref_instruction(incoming_values[i], irb->current_basic_block); - } - - return &phi_instruction->base; -} - static IrInstGen *ir_build_phi_gen(IrAnalyze *ira, IrInst *source_instr, size_t incoming_count, IrBasicBlockGen **incoming_blocks, IrInstGen **incoming_values, ZigType *result_type) { @@ -2591,20 +1319,6 @@ static IrInstGen *ir_build_phi_gen(IrAnalyze *ira, IrInst *source_instr, size_t return &phi_instruction->base; } -static IrInstSrc *ir_build_br(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrBasicBlockSrc *dest_block, IrInstSrc *is_comptime) -{ - IrInstSrcBr *inst = ir_build_instruction(irb, scope, source_node); - inst->base.is_noreturn = true; - inst->dest_block = dest_block; - inst->is_comptime = is_comptime; - - ir_ref_bb(dest_block); - if (is_comptime) ir_ref_instruction(is_comptime, irb->current_basic_block); - - return &inst->base; -} - static IrInstGen *ir_build_br_gen(IrAnalyze *ira, IrInst *source_instr, IrBasicBlockGen *dest_block) { IrInstGenBr *inst = ir_build_inst_noreturn(&ira->new_irb, source_instr->scope, source_instr->source_node); inst->dest_block = dest_block; @@ -2612,73 +1326,6 @@ static IrInstGen *ir_build_br_gen(IrAnalyze *ira, IrInst *source_instr, IrBasicB return &inst->base; } -static IrInstSrc *ir_build_ptr_type_simple(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *child_type, bool is_const) -{ - IrInstSrcPtrTypeSimple *inst = heap::c_allocator.create(); - inst->base.id = is_const ? IrInstSrcIdPtrTypeSimpleConst : IrInstSrcIdPtrTypeSimple; - inst->base.base.scope = scope; - inst->base.base.source_node = source_node; - inst->base.base.debug_id = exec_next_debug_id(irb->exec); - inst->base.owner_bb = irb->current_basic_block; - ir_instruction_append(irb->current_basic_block, &inst->base); - - inst->child_type = child_type; - - ir_ref_instruction(child_type, irb->current_basic_block); - - return &inst->base; -} - -static IrInstSrc *ir_build_ptr_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *child_type, bool is_const, bool is_volatile, PtrLen ptr_len, - IrInstSrc *sentinel, IrInstSrc *align_value, - uint32_t bit_offset_start, uint32_t host_int_bytes, bool is_allow_zero) -{ - if (!is_volatile && ptr_len == PtrLenSingle && sentinel == nullptr && align_value == nullptr && - bit_offset_start == 0 && host_int_bytes == 0 && is_allow_zero == 0) - { - return ir_build_ptr_type_simple(irb, scope, source_node, child_type, is_const); - } - - IrInstSrcPtrType *inst = ir_build_instruction(irb, scope, source_node); - inst->sentinel = sentinel; - inst->align_value = align_value; - inst->child_type = child_type; - inst->is_const = is_const; - inst->is_volatile = is_volatile; - inst->ptr_len = ptr_len; - inst->bit_offset_start = bit_offset_start; - inst->host_int_bytes = host_int_bytes; - inst->is_allow_zero = is_allow_zero; - - if (sentinel) ir_ref_instruction(sentinel, irb->current_basic_block); - if (align_value) ir_ref_instruction(align_value, irb->current_basic_block); - ir_ref_instruction(child_type, irb->current_basic_block); - - return &inst->base; -} - -static IrInstSrc *ir_build_un_op_lval(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrUnOp op_id, - IrInstSrc *value, LVal lval, ResultLoc *result_loc) -{ - IrInstSrcUnOp *instruction = ir_build_instruction(irb, scope, source_node); - instruction->op_id = op_id; - instruction->value = value; - instruction->lval = lval; - instruction->result_loc = result_loc; - - ir_ref_instruction(value, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstSrc *ir_build_un_op(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrUnOp op_id, - IrInstSrc *value) -{ - return ir_build_un_op_lval(irb, scope, source_node, op_id, value, LValNone, nullptr); -} - static IrInstGen *ir_build_negation(IrAnalyze *ira, IrInst *source_instr, IrInstGen *operand, ZigType *expr_type, bool wrapping) { IrInstGenNegation *instruction = ir_build_inst_gen(&ira->new_irb, source_instr->scope, source_instr->source_node); @@ -2704,66 +1351,11 @@ static IrInstGen *ir_build_binary_not(IrAnalyze *ira, IrInst *source_instr, IrIn return &instruction->base; } -static IrInstSrc *ir_build_container_init_list(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - size_t item_count, IrInstSrc **elem_result_loc_list, IrInstSrc *result_loc, - AstNode *init_array_type_source_node) -{ - IrInstSrcContainerInitList *container_init_list_instruction = - ir_build_instruction(irb, scope, source_node); - container_init_list_instruction->item_count = item_count; - container_init_list_instruction->elem_result_loc_list = elem_result_loc_list; - container_init_list_instruction->result_loc = result_loc; - container_init_list_instruction->init_array_type_source_node = init_array_type_source_node; - - for (size_t i = 0; i < item_count; i += 1) { - ir_ref_instruction(elem_result_loc_list[i], irb->current_basic_block); - } - if (result_loc != nullptr) ir_ref_instruction(result_loc, irb->current_basic_block); - - return &container_init_list_instruction->base; -} - -static IrInstSrc *ir_build_container_init_fields(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - size_t field_count, IrInstSrcContainerInitFieldsField *fields, IrInstSrc *result_loc) -{ - IrInstSrcContainerInitFields *container_init_fields_instruction = - ir_build_instruction(irb, scope, source_node); - container_init_fields_instruction->field_count = field_count; - container_init_fields_instruction->fields = fields; - container_init_fields_instruction->result_loc = result_loc; - - for (size_t i = 0; i < field_count; i += 1) { - ir_ref_instruction(fields[i].result_loc, irb->current_basic_block); - } - if (result_loc != nullptr) ir_ref_instruction(result_loc, irb->current_basic_block); - - return &container_init_fields_instruction->base; -} - -static IrInstSrc *ir_build_unreachable(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { - IrInstSrcUnreachable *inst = ir_build_instruction(irb, scope, source_node); - inst->base.is_noreturn = true; - return &inst->base; -} - static IrInstGen *ir_build_unreachable_gen(IrAnalyze *ira, IrInst *source_instr) { IrInstGenUnreachable *inst = ir_build_inst_noreturn(&ira->new_irb, source_instr->scope, source_instr->source_node); return &inst->base; } -static IrInstSrcStorePtr *ir_build_store_ptr(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *ptr, IrInstSrc *value) -{ - IrInstSrcStorePtr *instruction = ir_build_instruction(irb, scope, source_node); - instruction->ptr = ptr; - instruction->value = value; - - ir_ref_instruction(ptr, irb->current_basic_block); - ir_ref_instruction(value, irb->current_basic_block); - - return instruction; -} - static IrInstGen *ir_build_store_ptr_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *ptr, IrInstGen *value) { IrInstGenStorePtr *instruction = ir_build_inst_void(&ira->new_irb, source_instr->scope, source_instr->source_node); @@ -2792,20 +1384,6 @@ static IrInstGen *ir_build_vector_store_elem(IrAnalyze *ira, IrInst *src_inst, return &inst->base; } -static IrInstSrc *ir_build_var_decl_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - ZigVar *var, IrInstSrc *align_value, IrInstSrc *ptr) -{ - IrInstSrcDeclVar *inst = ir_build_instruction(irb, scope, source_node); - inst->var = var; - inst->align_value = align_value; - inst->ptr = ptr; - - if (align_value != nullptr) ir_ref_instruction(align_value, irb->current_basic_block); - ir_ref_instruction(ptr, irb->current_basic_block); - - return &inst->base; -} - static IrInstGen *ir_build_var_decl_gen(IrAnalyze *ira, IrInst *source_instruction, ZigVar *var, IrInstGen *var_ptr) { @@ -2821,34 +1399,6 @@ static IrInstGen *ir_build_var_decl_gen(IrAnalyze *ira, IrInst *source_instructi return &inst->base; } -static IrInstSrc *ir_build_export(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *target, IrInstSrc *options) -{ - IrInstSrcExport *export_instruction = ir_build_instruction( - irb, scope, source_node); - export_instruction->target = target; - export_instruction->options = options; - - ir_ref_instruction(target, irb->current_basic_block); - ir_ref_instruction(options, irb->current_basic_block); - - return &export_instruction->base; -} - -static IrInstSrc *ir_build_extern(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *type, IrInstSrc *options) -{ - IrInstSrcExtern *extern_instruction = ir_build_instruction( - irb, scope, source_node); - extern_instruction->type = type; - extern_instruction->options = options; - - ir_ref_instruction(type, irb->current_basic_block); - ir_ref_instruction(options, irb->current_basic_block); - - return &extern_instruction->base; -} - static IrInstGen *ir_build_extern_gen(IrAnalyze *ira, IrInst *source_instr, Buf *name, GlobalLinkageId linkage, bool is_thread_local, ZigType *expr_type) { @@ -2862,15 +1412,6 @@ static IrInstGen *ir_build_extern_gen(IrAnalyze *ira, IrInst *source_instr, Buf return &instruction->base; } -static IrInstSrc *ir_build_load_ptr(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *ptr) { - IrInstSrcLoadPtr *instruction = ir_build_instruction(irb, scope, source_node); - instruction->ptr = ptr; - - ir_ref_instruction(ptr, irb->current_basic_block); - - return &instruction->base; -} - static IrInstGen *ir_build_load_ptr_gen(IrAnalyze *ira, IrInst *source_instruction, IrInstGen *ptr, ZigType *ty, IrInstGen *result_loc) { @@ -2886,133 +1427,6 @@ static IrInstGen *ir_build_load_ptr_gen(IrAnalyze *ira, IrInst *source_instructi return &instruction->base; } -static IrInstSrc *ir_build_typeof_n(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc **values, size_t value_count) -{ - assert(value_count >= 2); - - IrInstSrcTypeOf *instruction = ir_build_instruction(irb, scope, source_node); - instruction->value.list = values; - instruction->value_count = value_count; - - for (size_t i = 0; i < value_count; i++) - ir_ref_instruction(values[i], irb->current_basic_block); - - return &instruction->base; -} - -static IrInstSrc *ir_build_typeof_1(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *value) { - IrInstSrcTypeOf *instruction = ir_build_instruction(irb, scope, source_node); - instruction->value.scalar = value; - - ir_ref_instruction(value, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstSrc *ir_build_set_cold(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *is_cold) { - IrInstSrcSetCold *instruction = ir_build_instruction(irb, scope, source_node); - instruction->is_cold = is_cold; - - ir_ref_instruction(is_cold, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstSrc *ir_build_set_runtime_safety(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *safety_on) -{ - IrInstSrcSetRuntimeSafety *inst = ir_build_instruction(irb, scope, source_node); - inst->safety_on = safety_on; - - ir_ref_instruction(safety_on, irb->current_basic_block); - - return &inst->base; -} - -static IrInstSrc *ir_build_set_float_mode(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *mode_value) -{ - IrInstSrcSetFloatMode *instruction = ir_build_instruction(irb, scope, source_node); - instruction->mode_value = mode_value; - - ir_ref_instruction(mode_value, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstSrc *ir_build_array_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *size, - IrInstSrc *sentinel, IrInstSrc *child_type) -{ - IrInstSrcArrayType *instruction = ir_build_instruction(irb, scope, source_node); - instruction->size = size; - instruction->sentinel = sentinel; - instruction->child_type = child_type; - - ir_ref_instruction(size, irb->current_basic_block); - if (sentinel != nullptr) ir_ref_instruction(sentinel, irb->current_basic_block); - ir_ref_instruction(child_type, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstSrc *ir_build_anyframe_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *payload_type) -{ - IrInstSrcAnyFrameType *instruction = ir_build_instruction(irb, scope, source_node); - instruction->payload_type = payload_type; - - if (payload_type != nullptr) ir_ref_instruction(payload_type, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstSrc *ir_build_slice_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *child_type, bool is_const, bool is_volatile, - IrInstSrc *sentinel, IrInstSrc *align_value, bool is_allow_zero) -{ - IrInstSrcSliceType *instruction = ir_build_instruction(irb, scope, source_node); - instruction->is_const = is_const; - instruction->is_volatile = is_volatile; - instruction->child_type = child_type; - instruction->sentinel = sentinel; - instruction->align_value = align_value; - instruction->is_allow_zero = is_allow_zero; - - if (sentinel != nullptr) ir_ref_instruction(sentinel, irb->current_basic_block); - if (align_value != nullptr) ir_ref_instruction(align_value, irb->current_basic_block); - ir_ref_instruction(child_type, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstSrc *ir_build_asm_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *asm_template, IrInstSrc **input_list, IrInstSrc **output_types, - ZigVar **output_vars, size_t return_count, bool has_side_effects, bool is_global) -{ - IrInstSrcAsm *instruction = ir_build_instruction(irb, scope, source_node); - instruction->asm_template = asm_template; - instruction->input_list = input_list; - instruction->output_types = output_types; - instruction->output_vars = output_vars; - instruction->return_count = return_count; - instruction->has_side_effects = has_side_effects; - instruction->is_global = is_global; - - assert(source_node->type == NodeTypeAsmExpr); - for (size_t i = 0; i < source_node->data.asm_expr.output_list.length; i += 1) { - IrInstSrc *output_type = output_types[i]; - if (output_type) ir_ref_instruction(output_type, irb->current_basic_block); - } - - for (size_t i = 0; i < source_node->data.asm_expr.input_list.length; i += 1) { - IrInstSrc *input_value = input_list[i]; - ir_ref_instruction(input_value, irb->current_basic_block); - } - - return &instruction->base; -} - static IrInstGen *ir_build_asm_gen(IrAnalyze *ira, IrInst *source_instr, Buf *asm_template, AsmToken *token_list, size_t token_list_len, IrInstGen **input_list, IrInstGen **output_types, ZigVar **output_vars, size_t return_count, @@ -3043,29 +1457,6 @@ static IrInstGen *ir_build_asm_gen(IrAnalyze *ira, IrInst *source_instr, return &instruction->base; } -static IrInstSrc *ir_build_size_of(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *type_value, - bool bit_size) -{ - IrInstSrcSizeOf *instruction = ir_build_instruction(irb, scope, source_node); - instruction->type_value = type_value; - instruction->bit_size = bit_size; - - ir_ref_instruction(type_value, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstSrc *ir_build_test_non_null_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *value) -{ - IrInstSrcTestNonNull *instruction = ir_build_instruction(irb, scope, source_node); - instruction->value = value; - - ir_ref_instruction(value, irb->current_basic_block); - - return &instruction->base; -} - static IrInstGen *ir_build_test_non_null_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *value) { IrInstGenTestNonNull *inst = ir_build_inst_gen(&ira->new_irb, source_instr->scope, source_instr->source_node); @@ -3077,18 +1468,6 @@ static IrInstGen *ir_build_test_non_null_gen(IrAnalyze *ira, IrInst *source_inst return &inst->base; } -static IrInstSrc *ir_build_optional_unwrap_ptr(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *base_ptr, bool safety_check_on) -{ - IrInstSrcOptionalUnwrapPtr *instruction = ir_build_instruction(irb, scope, source_node); - instruction->base_ptr = base_ptr; - instruction->safety_check_on = safety_check_on; - - ir_ref_instruction(base_ptr, irb->current_basic_block); - - return &instruction->base; -} - static IrInstGen *ir_build_optional_unwrap_ptr_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *base_ptr, bool safety_check_on, bool initializing, ZigType *result_type) { @@ -3149,19 +1528,6 @@ static IrInstGen *ir_build_err_wrap_code(IrAnalyze *ira, IrInst *source_instruct return &instruction->base; } -static IrInstSrc *ir_build_clz(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *type, - IrInstSrc *op) -{ - IrInstSrcClz *instruction = ir_build_instruction(irb, scope, source_node); - instruction->type = type; - instruction->op = op; - - ir_ref_instruction(type, irb->current_basic_block); - ir_ref_instruction(op, irb->current_basic_block); - - return &instruction->base; -} - static IrInstGen *ir_build_clz_gen(IrAnalyze *ira, IrInst *source_instr, ZigType *result_type, IrInstGen *op) { IrInstGenClz *instruction = ir_build_inst_gen(&ira->new_irb, source_instr->scope, source_instr->source_node); @@ -3173,19 +1539,6 @@ static IrInstGen *ir_build_clz_gen(IrAnalyze *ira, IrInst *source_instr, ZigType return &instruction->base; } -static IrInstSrc *ir_build_ctz(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *type, - IrInstSrc *op) -{ - IrInstSrcCtz *instruction = ir_build_instruction(irb, scope, source_node); - instruction->type = type; - instruction->op = op; - - ir_ref_instruction(type, irb->current_basic_block); - ir_ref_instruction(op, irb->current_basic_block); - - return &instruction->base; -} - static IrInstGen *ir_build_ctz_gen(IrAnalyze *ira, IrInst *source_instr, ZigType *result_type, IrInstGen *op) { IrInstGenCtz *instruction = ir_build_inst_gen(&ira->new_irb, source_instr->scope, source_instr->source_node); @@ -3197,19 +1550,6 @@ static IrInstGen *ir_build_ctz_gen(IrAnalyze *ira, IrInst *source_instr, ZigType return &instruction->base; } -static IrInstSrc *ir_build_pop_count(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *type, - IrInstSrc *op) -{ - IrInstSrcPopCount *instruction = ir_build_instruction(irb, scope, source_node); - instruction->type = type; - instruction->op = op; - - ir_ref_instruction(type, irb->current_basic_block); - ir_ref_instruction(op, irb->current_basic_block); - - return &instruction->base; -} - static IrInstGen *ir_build_pop_count_gen(IrAnalyze *ira, IrInst *source_instr, ZigType *result_type, IrInstGen *op) { @@ -3223,19 +1563,6 @@ static IrInstGen *ir_build_pop_count_gen(IrAnalyze *ira, IrInst *source_instr, Z return &instruction->base; } -static IrInstSrc *ir_build_bswap(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *type, - IrInstSrc *op) -{ - IrInstSrcBswap *instruction = ir_build_instruction(irb, scope, source_node); - instruction->type = type; - instruction->op = op; - - ir_ref_instruction(type, irb->current_basic_block); - ir_ref_instruction(op, irb->current_basic_block); - - return &instruction->base; -} - static IrInstGen *ir_build_bswap_gen(IrAnalyze *ira, IrInst *source_instr, ZigType *op_type, IrInstGen *op) { @@ -3249,19 +1576,6 @@ static IrInstGen *ir_build_bswap_gen(IrAnalyze *ira, IrInst *source_instr, ZigTy return &instruction->base; } -static IrInstSrc *ir_build_bit_reverse(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *type, - IrInstSrc *op) -{ - IrInstSrcBitReverse *instruction = ir_build_instruction(irb, scope, source_node); - instruction->type = type; - instruction->op = op; - - ir_ref_instruction(type, irb->current_basic_block); - ir_ref_instruction(op, irb->current_basic_block); - - return &instruction->base; -} - static IrInstGen *ir_build_bit_reverse_gen(IrAnalyze *ira, IrInst *source_instr, ZigType *int_type, IrInstGen *op) { @@ -3275,32 +1589,6 @@ static IrInstGen *ir_build_bit_reverse_gen(IrAnalyze *ira, IrInst *source_instr, return &instruction->base; } -static IrInstSrcSwitchBr *ir_build_switch_br_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *target_value, IrBasicBlockSrc *else_block, size_t case_count, IrInstSrcSwitchBrCase *cases, - IrInstSrc *is_comptime, IrInstSrc *switch_prongs_void) -{ - IrInstSrcSwitchBr *instruction = ir_build_instruction(irb, scope, source_node); - instruction->base.is_noreturn = true; - instruction->target_value = target_value; - instruction->else_block = else_block; - instruction->case_count = case_count; - instruction->cases = cases; - instruction->is_comptime = is_comptime; - instruction->switch_prongs_void = switch_prongs_void; - - ir_ref_instruction(target_value, irb->current_basic_block); - ir_ref_instruction(is_comptime, irb->current_basic_block); - ir_ref_bb(else_block); - ir_ref_instruction(switch_prongs_void, irb->current_basic_block); - - for (size_t i = 0; i < case_count; i += 1) { - ir_ref_instruction(cases[i].value, irb->current_basic_block); - ir_ref_bb(cases[i].block); - } - - return instruction; -} - static IrInstGenSwitchBr *ir_build_switch_br_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *target_value, IrBasicBlockGen *else_block, size_t case_count, IrInstGenSwitchBrCase *cases) { @@ -3320,45 +1608,6 @@ static IrInstGenSwitchBr *ir_build_switch_br_gen(IrAnalyze *ira, IrInst *source_ return instruction; } -static IrInstSrc *ir_build_switch_target(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *target_value_ptr) -{ - IrInstSrcSwitchTarget *instruction = ir_build_instruction(irb, scope, source_node); - instruction->target_value_ptr = target_value_ptr; - - ir_ref_instruction(target_value_ptr, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstSrc *ir_build_switch_var(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *target_value_ptr, IrInstSrc **prongs_ptr, size_t prongs_len) -{ - IrInstSrcSwitchVar *instruction = ir_build_instruction(irb, scope, source_node); - instruction->target_value_ptr = target_value_ptr; - instruction->prongs_ptr = prongs_ptr; - instruction->prongs_len = prongs_len; - - ir_ref_instruction(target_value_ptr, irb->current_basic_block); - for (size_t i = 0; i < prongs_len; i += 1) { - ir_ref_instruction(prongs_ptr[i], irb->current_basic_block); - } - - return &instruction->base; -} - -// For this instruction the switch_br must be set later. -static IrInstSrcSwitchElseVar *ir_build_switch_else_var(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *target_value_ptr) -{ - IrInstSrcSwitchElseVar *instruction = ir_build_instruction(irb, scope, source_node); - instruction->target_value_ptr = target_value_ptr; - - ir_ref_instruction(target_value_ptr, irb->current_basic_block); - - return instruction; -} - static IrInstGen *ir_build_union_tag(IrAnalyze *ira, IrInst *source_instr, IrInstGen *value, ZigType *tag_type) { @@ -3372,24 +1621,6 @@ static IrInstGen *ir_build_union_tag(IrAnalyze *ira, IrInst *source_instr, IrIns return &instruction->base; } -static IrInstSrc *ir_build_import(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *name) { - IrInstSrcImport *instruction = ir_build_instruction(irb, scope, source_node); - instruction->name = name; - - ir_ref_instruction(name, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstSrc *ir_build_ref_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *value) { - IrInstSrcRef *instruction = ir_build_instruction(irb, scope, source_node); - instruction->value = value; - - ir_ref_instruction(value, irb->current_basic_block); - - return &instruction->base; -} - static IrInstGen *ir_build_ref_gen(IrAnalyze *ira, IrInst *source_instruction, ZigType *result_type, IrInstGen *operand, IrInstGen *result_loc) { @@ -3405,38 +1636,6 @@ static IrInstGen *ir_build_ref_gen(IrAnalyze *ira, IrInst *source_instruction, Z return &instruction->base; } -static IrInstSrc *ir_build_compile_err(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *msg) { - IrInstSrcCompileErr *instruction = ir_build_instruction(irb, scope, source_node); - instruction->msg = msg; - - ir_ref_instruction(msg, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstSrc *ir_build_compile_log(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - size_t msg_count, IrInstSrc **msg_list) -{ - IrInstSrcCompileLog *instruction = ir_build_instruction(irb, scope, source_node); - instruction->msg_count = msg_count; - instruction->msg_list = msg_list; - - for (size_t i = 0; i < msg_count; i += 1) { - ir_ref_instruction(msg_list[i], irb->current_basic_block); - } - - return &instruction->base; -} - -static IrInstSrc *ir_build_err_name(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *value) { - IrInstSrcErrName *instruction = ir_build_instruction(irb, scope, source_node); - instruction->value = value; - - ir_ref_instruction(value, irb->current_basic_block); - - return &instruction->base; -} - static IrInstGen *ir_build_err_name_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *value, ZigType *str_type) { @@ -3450,73 +1649,6 @@ static IrInstGen *ir_build_err_name_gen(IrAnalyze *ira, IrInst *source_instr, Ir return &instruction->base; } -static IrInstSrc *ir_build_c_import(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { - IrInstSrcCImport *instruction = ir_build_instruction(irb, scope, source_node); - return &instruction->base; -} - -static IrInstSrc *ir_build_c_include(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *name) { - IrInstSrcCInclude *instruction = ir_build_instruction(irb, scope, source_node); - instruction->name = name; - - ir_ref_instruction(name, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstSrc *ir_build_c_define(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *name, IrInstSrc *value) { - IrInstSrcCDefine *instruction = ir_build_instruction(irb, scope, source_node); - instruction->name = name; - instruction->value = value; - - ir_ref_instruction(name, irb->current_basic_block); - ir_ref_instruction(value, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstSrc *ir_build_c_undef(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *name) { - IrInstSrcCUndef *instruction = ir_build_instruction(irb, scope, source_node); - instruction->name = name; - - ir_ref_instruction(name, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstSrc *ir_build_embed_file(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *name) { - IrInstSrcEmbedFile *instruction = ir_build_instruction(irb, scope, source_node); - instruction->name = name; - - ir_ref_instruction(name, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstSrc *ir_build_cmpxchg_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *type_value, IrInstSrc *ptr, IrInstSrc *cmp_value, IrInstSrc *new_value, - IrInstSrc *success_order_value, IrInstSrc *failure_order_value, bool is_weak, ResultLoc *result_loc) -{ - IrInstSrcCmpxchg *instruction = ir_build_instruction(irb, scope, source_node); - instruction->type_value = type_value; - instruction->ptr = ptr; - instruction->cmp_value = cmp_value; - instruction->new_value = new_value; - instruction->success_order_value = success_order_value; - instruction->failure_order_value = failure_order_value; - instruction->is_weak = is_weak; - instruction->result_loc = result_loc; - - ir_ref_instruction(type_value, irb->current_basic_block); - ir_ref_instruction(ptr, irb->current_basic_block); - ir_ref_instruction(cmp_value, irb->current_basic_block); - ir_ref_instruction(new_value, irb->current_basic_block); - ir_ref_instruction(success_order_value, irb->current_basic_block); - ir_ref_instruction(failure_order_value, irb->current_basic_block); - - return &instruction->base; -} - static IrInstGen *ir_build_cmpxchg_gen(IrAnalyze *ira, IrInst *source_instruction, ZigType *result_type, IrInstGen *ptr, IrInstGen *cmp_value, IrInstGen *new_value, AtomicOrder success_order, AtomicOrder failure_order, bool is_weak, IrInstGen *result_loc) @@ -3540,15 +1672,6 @@ static IrInstGen *ir_build_cmpxchg_gen(IrAnalyze *ira, IrInst *source_instructio return &instruction->base; } -static IrInstSrc *ir_build_fence(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *order) { - IrInstSrcFence *instruction = ir_build_instruction(irb, scope, source_node); - instruction->order = order; - - ir_ref_instruction(order, irb->current_basic_block); - - return &instruction->base; -} - static IrInstGen *ir_build_fence_gen(IrAnalyze *ira, IrInst *source_instr, AtomicOrder order) { IrInstGenFence *instruction = ir_build_inst_void(&ira->new_irb, source_instr->scope, source_instr->source_node); @@ -3557,17 +1680,6 @@ static IrInstGen *ir_build_fence_gen(IrAnalyze *ira, IrInst *source_instr, Atomi return &instruction->base; } -static IrInstSrc *ir_build_reduce(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *op, IrInstSrc *value) { - IrInstSrcReduce *instruction = ir_build_instruction(irb, scope, source_node); - instruction->op = op; - instruction->value = value; - - ir_ref_instruction(op, irb->current_basic_block); - ir_ref_instruction(value, irb->current_basic_block); - - return &instruction->base; -} - static IrInstGen *ir_build_reduce_gen(IrAnalyze *ira, IrInst *source_instruction, ReduceOp op, IrInstGen *value, ZigType *result_type) { IrInstGenReduce *instruction = ir_build_inst_gen(&ira->new_irb, source_instruction->scope, source_instruction->source_node); @@ -3580,17 +1692,32 @@ static IrInstGen *ir_build_reduce_gen(IrAnalyze *ira, IrInst *source_instruction return &instruction->base; } -static IrInstSrc *ir_build_truncate(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *dest_type, IrInstSrc *target) -{ - IrInstSrcTruncate *instruction = ir_build_instruction(irb, scope, source_node); - instruction->dest_type = dest_type; - instruction->target = target; +static void ir_set_cursor_at_end_gen(IrBuilderGen *irb, IrBasicBlockGen *basic_block) { + assert(basic_block); + irb->current_basic_block = basic_block; +} - ir_ref_instruction(dest_type, irb->current_basic_block); - ir_ref_instruction(target, irb->current_basic_block); +static void ir_append_basic_block_gen(IrBuilderGen *irb, IrBasicBlockGen *bb) { + assert(!bb->already_appended); + bb->already_appended = true; + irb->exec->basic_block_list.append(bb); +} - return &instruction->base; +static void ir_set_cursor_at_end_and_append_block_gen(IrBuilderGen *irb, IrBasicBlockGen *basic_block) { + ir_append_basic_block_gen(irb, basic_block); + ir_set_cursor_at_end_gen(irb, basic_block); +} + +static IrInstGen *ir_build_suspend_begin_gen(IrAnalyze *ira, IrInst *source_instr) { + IrInstGenSuspendBegin *inst = ir_build_inst_void(&ira->new_irb, + source_instr->scope, source_instr->source_node); + return &inst->base; +} + +static IrInstGen *ir_build_save_err_ret_addr_gen(IrAnalyze *ira, IrInst *source_instr) { + IrInstGenSaveErrRetAddr *inst = ir_build_inst_void(&ira->new_irb, + source_instr->scope, source_instr->source_node); + return &inst->base; } static IrInstGen *ir_build_truncate_gen(IrAnalyze *ira, IrInst *source_instr, ZigType *dest_type, @@ -3606,110 +1733,6 @@ static IrInstGen *ir_build_truncate_gen(IrAnalyze *ira, IrInst *source_instr, Zi return &instruction->base; } -static IrInstSrc *ir_build_int_cast(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *dest_type, - IrInstSrc *target) -{ - IrInstSrcIntCast *instruction = ir_build_instruction(irb, scope, source_node); - instruction->dest_type = dest_type; - instruction->target = target; - - ir_ref_instruction(dest_type, irb->current_basic_block); - ir_ref_instruction(target, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstSrc *ir_build_float_cast(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *dest_type, - IrInstSrc *target) -{ - IrInstSrcFloatCast *instruction = ir_build_instruction(irb, scope, source_node); - instruction->dest_type = dest_type; - instruction->target = target; - - ir_ref_instruction(dest_type, irb->current_basic_block); - ir_ref_instruction(target, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstSrc *ir_build_err_set_cast(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *dest_type, IrInstSrc *target) -{ - IrInstSrcErrSetCast *instruction = ir_build_instruction(irb, scope, source_node); - instruction->dest_type = dest_type; - instruction->target = target; - - ir_ref_instruction(dest_type, irb->current_basic_block); - ir_ref_instruction(target, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstSrc *ir_build_int_to_float(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *dest_type, IrInstSrc *target) -{ - IrInstSrcIntToFloat *instruction = ir_build_instruction(irb, scope, source_node); - instruction->dest_type = dest_type; - instruction->target = target; - - ir_ref_instruction(dest_type, irb->current_basic_block); - ir_ref_instruction(target, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstSrc *ir_build_float_to_int(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *dest_type, IrInstSrc *target) -{ - IrInstSrcFloatToInt *instruction = ir_build_instruction(irb, scope, source_node); - instruction->dest_type = dest_type; - instruction->target = target; - - ir_ref_instruction(dest_type, irb->current_basic_block); - ir_ref_instruction(target, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstSrc *ir_build_bool_to_int(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *target) { - IrInstSrcBoolToInt *instruction = ir_build_instruction(irb, scope, source_node); - instruction->target = target; - - ir_ref_instruction(target, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstSrc *ir_build_vector_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *len, - IrInstSrc *elem_type) -{ - IrInstSrcVectorType *instruction = ir_build_instruction(irb, scope, source_node); - instruction->len = len; - instruction->elem_type = elem_type; - - ir_ref_instruction(len, irb->current_basic_block); - ir_ref_instruction(elem_type, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstSrc *ir_build_shuffle_vector(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *scalar_type, IrInstSrc *a, IrInstSrc *b, IrInstSrc *mask) -{ - IrInstSrcShuffleVector *instruction = ir_build_instruction(irb, scope, source_node); - instruction->scalar_type = scalar_type; - instruction->a = a; - instruction->b = b; - instruction->mask = mask; - - if (scalar_type != nullptr) ir_ref_instruction(scalar_type, irb->current_basic_block); - ir_ref_instruction(a, irb->current_basic_block); - ir_ref_instruction(b, irb->current_basic_block); - ir_ref_instruction(mask, irb->current_basic_block); - - return &instruction->base; -} - static IrInstGen *ir_build_shuffle_vector_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, ZigType *result_type, IrInstGen *a, IrInstGen *b, IrInstGen *mask) { @@ -3726,19 +1749,6 @@ static IrInstGen *ir_build_shuffle_vector_gen(IrAnalyze *ira, Scope *scope, AstN return &inst->base; } -static IrInstSrc *ir_build_splat_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *len, IrInstSrc *scalar) -{ - IrInstSrcSplat *instruction = ir_build_instruction(irb, scope, source_node); - instruction->len = len; - instruction->scalar = scalar; - - ir_ref_instruction(len, irb->current_basic_block); - ir_ref_instruction(scalar, irb->current_basic_block); - - return &instruction->base; -} - static IrInstGen *ir_build_splat_gen(IrAnalyze *ira, IrInst *source_instruction, ZigType *result_type, IrInstGen *scalar) { @@ -3752,15 +1762,6 @@ static IrInstGen *ir_build_splat_gen(IrAnalyze *ira, IrInst *source_instruction, return &instruction->base; } -static IrInstSrc *ir_build_bool_not(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *value) { - IrInstSrcBoolNot *instruction = ir_build_instruction(irb, scope, source_node); - instruction->value = value; - - ir_ref_instruction(value, irb->current_basic_block); - - return &instruction->base; -} - static IrInstGen *ir_build_bool_not_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *value) { IrInstGenBoolNot *instruction = ir_build_inst_gen(&ira->new_irb, source_instr->scope, source_instr->source_node); @@ -3772,21 +1773,6 @@ static IrInstGen *ir_build_bool_not_gen(IrAnalyze *ira, IrInst *source_instr, Ir return &instruction->base; } -static IrInstSrc *ir_build_memset_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *dest_ptr, IrInstSrc *byte, IrInstSrc *count) -{ - IrInstSrcMemset *instruction = ir_build_instruction(irb, scope, source_node); - instruction->dest_ptr = dest_ptr; - instruction->byte = byte; - instruction->count = count; - - ir_ref_instruction(dest_ptr, irb->current_basic_block); - ir_ref_instruction(byte, irb->current_basic_block); - ir_ref_instruction(count, irb->current_basic_block); - - return &instruction->base; -} - static IrInstGen *ir_build_memset_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *dest_ptr, IrInstGen *byte, IrInstGen *count) { @@ -3803,21 +1789,6 @@ static IrInstGen *ir_build_memset_gen(IrAnalyze *ira, IrInst *source_instr, return &instruction->base; } -static IrInstSrc *ir_build_memcpy_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *dest_ptr, IrInstSrc *src_ptr, IrInstSrc *count) -{ - IrInstSrcMemcpy *instruction = ir_build_instruction(irb, scope, source_node); - instruction->dest_ptr = dest_ptr; - instruction->src_ptr = src_ptr; - instruction->count = count; - - ir_ref_instruction(dest_ptr, irb->current_basic_block); - ir_ref_instruction(src_ptr, irb->current_basic_block); - ir_ref_instruction(count, irb->current_basic_block); - - return &instruction->base; -} - static IrInstGen *ir_build_memcpy_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *dest_ptr, IrInstGen *src_ptr, IrInstGen *count) { @@ -3834,26 +1805,6 @@ static IrInstGen *ir_build_memcpy_gen(IrAnalyze *ira, IrInst *source_instr, return &instruction->base; } -static IrInstSrc *ir_build_slice_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *ptr, IrInstSrc *start, IrInstSrc *end, IrInstSrc *sentinel, - bool safety_check_on, ResultLoc *result_loc) -{ - IrInstSrcSlice *instruction = ir_build_instruction(irb, scope, source_node); - instruction->ptr = ptr; - instruction->start = start; - instruction->end = end; - instruction->sentinel = sentinel; - instruction->safety_check_on = safety_check_on; - instruction->result_loc = result_loc; - - ir_ref_instruction(ptr, irb->current_basic_block); - ir_ref_instruction(start, irb->current_basic_block); - if (end) ir_ref_instruction(end, irb->current_basic_block); - if (sentinel) ir_ref_instruction(sentinel, irb->current_basic_block); - - return &instruction->base; -} - static IrInstGen *ir_build_slice_gen(IrAnalyze *ira, IrInst *source_instruction, ZigType *slice_type, IrInstGen *ptr, IrInstGen *start, IrInstGen *end, bool safety_check_on, IrInstGen *result_loc, ZigValue *sentinel) @@ -3876,68 +1827,30 @@ static IrInstGen *ir_build_slice_gen(IrAnalyze *ira, IrInst *source_instruction, return &instruction->base; } -static IrInstSrc *ir_build_breakpoint(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { - IrInstSrcBreakpoint *instruction = ir_build_instruction(irb, scope, source_node); - return &instruction->base; -} - static IrInstGen *ir_build_breakpoint_gen(IrAnalyze *ira, IrInst *source_instr) { IrInstGenBreakpoint *instruction = ir_build_inst_void(&ira->new_irb, source_instr->scope, source_instr->source_node); return &instruction->base; } -static IrInstSrc *ir_build_return_address_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { - IrInstSrcReturnAddress *instruction = ir_build_instruction(irb, scope, source_node); - return &instruction->base; -} - static IrInstGen *ir_build_return_address_gen(IrAnalyze *ira, IrInst *source_instr) { IrInstGenReturnAddress *inst = ir_build_inst_gen(&ira->new_irb, source_instr->scope, source_instr->source_node); inst->base.value->type = ira->codegen->builtin_types.entry_usize; return &inst->base; } -static IrInstSrc *ir_build_frame_address_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { - IrInstSrcFrameAddress *inst = ir_build_instruction(irb, scope, source_node); - return &inst->base; -} - static IrInstGen *ir_build_frame_address_gen(IrAnalyze *ira, IrInst *source_instr) { IrInstGenFrameAddress *inst = ir_build_inst_gen(&ira->new_irb, source_instr->scope, source_instr->source_node); inst->base.value->type = ira->codegen->builtin_types.entry_usize; return &inst->base; } -static IrInstSrc *ir_build_handle_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { - IrInstSrcFrameHandle *inst = ir_build_instruction(irb, scope, source_node); - return &inst->base; -} - static IrInstGen *ir_build_handle_gen(IrAnalyze *ira, IrInst *source_instr, ZigType *ty) { IrInstGenFrameHandle *inst = ir_build_inst_gen(&ira->new_irb, source_instr->scope, source_instr->source_node); inst->base.value->type = ty; return &inst->base; } -static IrInstSrc *ir_build_frame_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *fn) { - IrInstSrcFrameType *inst = ir_build_instruction(irb, scope, source_node); - inst->fn = fn; - - ir_ref_instruction(fn, irb->current_basic_block); - - return &inst->base; -} - -static IrInstSrc *ir_build_frame_size_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *fn) { - IrInstSrcFrameSize *inst = ir_build_instruction(irb, scope, source_node); - inst->fn = fn; - - ir_ref_instruction(fn, irb->current_basic_block); - - return &inst->base; -} - static IrInstGen *ir_build_frame_size_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *fn) { IrInstGenFrameSize *inst = ir_build_inst_gen(&ira->new_irb, source_instr->scope, source_instr->source_node); @@ -3949,24 +1862,6 @@ static IrInstGen *ir_build_frame_size_gen(IrAnalyze *ira, IrInst *source_instr, return &inst->base; } -static IrInstSrc *ir_build_overflow_op_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrOverflowOp op, IrInstSrc *type_value, IrInstSrc *op1, IrInstSrc *op2, IrInstSrc *result_ptr) -{ - IrInstSrcOverflowOp *instruction = ir_build_instruction(irb, scope, source_node); - instruction->op = op; - instruction->type_value = type_value; - instruction->op1 = op1; - instruction->op2 = op2; - instruction->result_ptr = result_ptr; - - ir_ref_instruction(type_value, irb->current_basic_block); - ir_ref_instruction(op1, irb->current_basic_block); - ir_ref_instruction(op2, irb->current_basic_block); - ir_ref_instruction(result_ptr, irb->current_basic_block); - - return &instruction->base; -} - static IrInstGen *ir_build_overflow_op_gen(IrAnalyze *ira, IrInst *source_instr, IrOverflowOp op, IrInstGen *op1, IrInstGen *op2, IrInstGen *result_ptr, ZigType *result_ptr_type) @@ -3987,18 +1882,6 @@ static IrInstGen *ir_build_overflow_op_gen(IrAnalyze *ira, IrInst *source_instr, return &instruction->base; } -static IrInstSrc *ir_build_float_op_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *operand, - BuiltinFnId fn_id) -{ - IrInstSrcFloatOp *instruction = ir_build_instruction(irb, scope, source_node); - instruction->operand = operand; - instruction->fn_id = fn_id; - - ir_ref_instruction(operand, irb->current_basic_block); - - return &instruction->base; -} - static IrInstGen *ir_build_float_op_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *operand, BuiltinFnId fn_id, ZigType *operand_type) { @@ -4013,23 +1896,6 @@ static IrInstGen *ir_build_float_op_gen(IrAnalyze *ira, IrInst *source_instr, Ir return &instruction->base; } -static IrInstSrc *ir_build_mul_add_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *type_value, IrInstSrc *op1, IrInstSrc *op2, IrInstSrc *op3) -{ - IrInstSrcMulAdd *instruction = ir_build_instruction(irb, scope, source_node); - instruction->type_value = type_value; - instruction->op1 = op1; - instruction->op2 = op2; - instruction->op3 = op3; - - ir_ref_instruction(type_value, irb->current_basic_block); - ir_ref_instruction(op1, irb->current_basic_block); - ir_ref_instruction(op2, irb->current_basic_block); - ir_ref_instruction(op3, irb->current_basic_block); - - return &instruction->base; -} - static IrInstGen *ir_build_mul_add_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *op1, IrInstGen *op2, IrInstGen *op3, ZigType *expr_type) { @@ -4047,28 +1913,6 @@ static IrInstGen *ir_build_mul_add_gen(IrAnalyze *ira, IrInst *source_instr, IrI return &instruction->base; } -static IrInstSrc *ir_build_align_of(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *type_value) { - IrInstSrcAlignOf *instruction = ir_build_instruction(irb, scope, source_node); - instruction->type_value = type_value; - - ir_ref_instruction(type_value, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstSrc *ir_build_test_err_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *base_ptr, bool resolve_err_set, bool base_ptr_is_payload) -{ - IrInstSrcTestErr *instruction = ir_build_instruction(irb, scope, source_node); - instruction->base_ptr = base_ptr; - instruction->resolve_err_set = resolve_err_set; - instruction->base_ptr_is_payload = base_ptr_is_payload; - - ir_ref_instruction(base_ptr, irb->current_basic_block); - - return &instruction->base; -} - static IrInstGen *ir_build_test_err_gen(IrAnalyze *ira, IrInst *source_instruction, IrInstGen *err_union) { IrInstGenTestErr *instruction = ir_build_inst_gen( &ira->new_irb, source_instruction->scope, source_instruction->source_node); @@ -4080,17 +1924,6 @@ static IrInstGen *ir_build_test_err_gen(IrAnalyze *ira, IrInst *source_instructi return &instruction->base; } -static IrInstSrc *ir_build_unwrap_err_code_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *err_union_ptr) -{ - IrInstSrcUnwrapErrCode *inst = ir_build_instruction(irb, scope, source_node); - inst->err_union_ptr = err_union_ptr; - - ir_ref_instruction(err_union_ptr, irb->current_basic_block); - - return &inst->base; -} - static IrInstGen *ir_build_unwrap_err_code_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, IrInstGen *err_union_ptr, ZigType *result_type) { @@ -4103,19 +1936,6 @@ static IrInstGen *ir_build_unwrap_err_code_gen(IrAnalyze *ira, Scope *scope, Ast return &inst->base; } -static IrInstSrc *ir_build_unwrap_err_payload_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *value, bool safety_check_on, bool initializing) -{ - IrInstSrcUnwrapErrPayload *inst = ir_build_instruction(irb, scope, source_node); - inst->value = value; - inst->safety_check_on = safety_check_on; - inst->initializing = initializing; - - ir_ref_instruction(value, irb->current_basic_block); - - return &inst->base; -} - static IrInstGen *ir_build_unwrap_err_payload_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, IrInstGen *value, bool safety_check_on, bool initializing, ZigType *result_type) { @@ -4130,54 +1950,6 @@ static IrInstGen *ir_build_unwrap_err_payload_gen(IrAnalyze *ira, Scope *scope, return &inst->base; } -static IrInstSrc *ir_build_fn_proto(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc **param_types, IrInstSrc *align_value, IrInstSrc *callconv_value, - IrInstSrc *return_type, bool is_var_args) -{ - IrInstSrcFnProto *instruction = ir_build_instruction(irb, scope, source_node); - instruction->param_types = param_types; - instruction->align_value = align_value; - instruction->callconv_value = callconv_value; - instruction->return_type = return_type; - instruction->is_var_args = is_var_args; - - assert(source_node->type == NodeTypeFnProto); - size_t param_count = source_node->data.fn_proto.params.length; - if (is_var_args) param_count -= 1; - for (size_t i = 0; i < param_count; i += 1) { - if (param_types[i] != nullptr) ir_ref_instruction(param_types[i], irb->current_basic_block); - } - if (align_value != nullptr) ir_ref_instruction(align_value, irb->current_basic_block); - if (callconv_value != nullptr) ir_ref_instruction(callconv_value, irb->current_basic_block); - ir_ref_instruction(return_type, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstSrc *ir_build_test_comptime(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *value) { - IrInstSrcTestComptime *instruction = ir_build_instruction(irb, scope, source_node); - instruction->value = value; - - ir_ref_instruction(value, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstSrc *ir_build_ptr_cast_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *dest_type, IrInstSrc *ptr, bool safety_check_on) -{ - IrInstSrcPtrCast *instruction = ir_build_instruction( - irb, scope, source_node); - instruction->dest_type = dest_type; - instruction->ptr = ptr; - instruction->safety_check_on = safety_check_on; - - ir_ref_instruction(dest_type, irb->current_basic_block); - ir_ref_instruction(ptr, irb->current_basic_block); - - return &instruction->base; -} - static IrInstGen *ir_build_ptr_cast_gen(IrAnalyze *ira, IrInst *source_instruction, ZigType *ptr_type, IrInstGen *ptr, bool safety_check_on) { @@ -4192,30 +1964,6 @@ static IrInstGen *ir_build_ptr_cast_gen(IrAnalyze *ira, IrInst *source_instructi return &instruction->base; } -static IrInstSrc *ir_build_implicit_cast(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *operand, ResultLocCast *result_loc_cast) -{ - IrInstSrcImplicitCast *instruction = ir_build_instruction(irb, scope, source_node); - instruction->operand = operand; - instruction->result_loc_cast = result_loc_cast; - - ir_ref_instruction(operand, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstSrc *ir_build_bit_cast_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *operand, ResultLocBitCast *result_loc_bit_cast) -{ - IrInstSrcBitCast *instruction = ir_build_instruction(irb, scope, source_node); - instruction->operand = operand; - instruction->result_loc_bit_cast = result_loc_bit_cast; - - ir_ref_instruction(operand, irb->current_basic_block); - - return &instruction->base; -} - static IrInstGen *ir_build_bit_cast_gen(IrAnalyze *ira, IrInst *source_instruction, IrInstGen *operand, ZigType *ty) { @@ -4241,19 +1989,6 @@ static IrInstGen *ir_build_widen_or_shorten(IrAnalyze *ira, Scope *scope, AstNod return &inst->base; } -static IrInstSrc *ir_build_int_to_ptr_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *dest_type, IrInstSrc *target) -{ - IrInstSrcIntToPtr *instruction = ir_build_instruction(irb, scope, source_node); - instruction->dest_type = dest_type; - instruction->target = target; - - ir_ref_instruction(dest_type, irb->current_basic_block); - ir_ref_instruction(target, irb->current_basic_block); - - return &instruction->base; -} - static IrInstGen *ir_build_int_to_ptr_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, IrInstGen *target, ZigType *ptr_type) { @@ -4266,17 +2001,6 @@ static IrInstGen *ir_build_int_to_ptr_gen(IrAnalyze *ira, Scope *scope, AstNode return &instruction->base; } -static IrInstSrc *ir_build_ptr_to_int_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *target) -{ - IrInstSrcPtrToInt *inst = ir_build_instruction(irb, scope, source_node); - inst->target = target; - - ir_ref_instruction(target, irb->current_basic_block); - - return &inst->base; -} - static IrInstGen *ir_build_ptr_to_int_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *target) { IrInstGenPtrToInt *inst = ir_build_inst_gen(&ira->new_irb, source_instr->scope, source_instr->source_node); inst->base.value->type = ira->codegen->builtin_types.entry_usize; @@ -4287,19 +2011,6 @@ static IrInstGen *ir_build_ptr_to_int_gen(IrAnalyze *ira, IrInst *source_instr, return &inst->base; } -static IrInstSrc *ir_build_int_to_enum_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *dest_type, IrInstSrc *target) -{ - IrInstSrcIntToEnum *instruction = ir_build_instruction(irb, scope, source_node); - instruction->dest_type = dest_type; - instruction->target = target; - - if (dest_type) ir_ref_instruction(dest_type, irb->current_basic_block); - ir_ref_instruction(target, irb->current_basic_block); - - return &instruction->base; -} - static IrInstGen *ir_build_int_to_enum_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, ZigType *dest_type, IrInstGen *target) { @@ -4312,29 +2023,6 @@ static IrInstGen *ir_build_int_to_enum_gen(IrAnalyze *ira, Scope *scope, AstNode return &instruction->base; } -static IrInstSrc *ir_build_enum_to_int(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *target) -{ - IrInstSrcEnumToInt *instruction = ir_build_instruction( - irb, scope, source_node); - instruction->target = target; - - ir_ref_instruction(target, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstSrc *ir_build_int_to_err_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *target) -{ - IrInstSrcIntToErr *instruction = ir_build_instruction(irb, scope, source_node); - instruction->target = target; - - ir_ref_instruction(target, irb->current_basic_block); - - return &instruction->base; -} - static IrInstGen *ir_build_int_to_err_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, IrInstGen *target, ZigType *wanted_type) { @@ -4347,18 +2035,6 @@ static IrInstGen *ir_build_int_to_err_gen(IrAnalyze *ira, Scope *scope, AstNode return &instruction->base; } -static IrInstSrc *ir_build_err_to_int_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *target) -{ - IrInstSrcErrToInt *instruction = ir_build_instruction( - irb, scope, source_node); - instruction->target = target; - - ir_ref_instruction(target, irb->current_basic_block); - - return &instruction->base; -} - static IrInstGen *ir_build_err_to_int_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, IrInstGen *target, ZigType *wanted_type) { @@ -4371,74 +2047,6 @@ static IrInstGen *ir_build_err_to_int_gen(IrAnalyze *ira, Scope *scope, AstNode return &instruction->base; } -static IrInstSrc *ir_build_check_switch_prongs(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *target_value, IrInstSrcCheckSwitchProngsRange *ranges, size_t range_count, - AstNode* else_prong, bool have_underscore_prong) -{ - IrInstSrcCheckSwitchProngs *instruction = heap::c_allocator.create(); - instruction->base.id = have_underscore_prong ? - IrInstSrcIdCheckSwitchProngsUnderYes : IrInstSrcIdCheckSwitchProngsUnderNo; - instruction->base.base.scope = scope; - instruction->base.base.source_node = source_node; - instruction->base.base.debug_id = exec_next_debug_id(irb->exec); - instruction->base.owner_bb = irb->current_basic_block; - ir_instruction_append(irb->current_basic_block, &instruction->base); - - instruction->target_value = target_value; - instruction->ranges = ranges; - instruction->range_count = range_count; - instruction->else_prong = else_prong; - - ir_ref_instruction(target_value, irb->current_basic_block); - for (size_t i = 0; i < range_count; i += 1) { - ir_ref_instruction(ranges[i].start, irb->current_basic_block); - ir_ref_instruction(ranges[i].end, irb->current_basic_block); - } - - return &instruction->base; -} - -static IrInstSrc *ir_build_check_statement_is_void(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc* statement_value) -{ - IrInstSrcCheckStatementIsVoid *instruction = ir_build_instruction( - irb, scope, source_node); - instruction->statement_value = statement_value; - - ir_ref_instruction(statement_value, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstSrc *ir_build_type_name(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *type_value) -{ - IrInstSrcTypeName *instruction = ir_build_instruction(irb, scope, source_node); - instruction->type_value = type_value; - - ir_ref_instruction(type_value, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstSrc *ir_build_decl_ref(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, Tld *tld, LVal lval) { - IrInstSrcDeclRef *instruction = ir_build_instruction(irb, scope, source_node); - instruction->tld = tld; - instruction->lval = lval; - - return &instruction->base; -} - -static IrInstSrc *ir_build_panic_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *msg) { - IrInstSrcPanic *instruction = ir_build_instruction(irb, scope, source_node); - instruction->base.is_noreturn = true; - instruction->msg = msg; - - ir_ref_instruction(msg, irb->current_basic_block); - - return &instruction->base; -} - static IrInstGen *ir_build_panic_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *msg) { IrInstGenPanic *instruction = ir_build_inst_noreturn(&ira->new_irb, source_instr->scope, source_instr->source_node); @@ -4449,15 +2057,6 @@ static IrInstGen *ir_build_panic_gen(IrAnalyze *ira, IrInst *source_instr, IrIns return &instruction->base; } -static IrInstSrc *ir_build_tag_name_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *target) { - IrInstSrcTagName *instruction = ir_build_instruction(irb, scope, source_node); - instruction->target = target; - - ir_ref_instruction(target, irb->current_basic_block); - - return &instruction->base; -} - static IrInstGen *ir_build_tag_name_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *target, ZigType *result_type) { @@ -4471,22 +2070,6 @@ static IrInstGen *ir_build_tag_name_gen(IrAnalyze *ira, IrInst *source_instr, Ir return &instruction->base; } -static IrInstSrc *ir_build_field_parent_ptr_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *type_value, IrInstSrc *field_name, IrInstSrc *field_ptr) -{ - IrInstSrcFieldParentPtr *inst = ir_build_instruction( - irb, scope, source_node); - inst->type_value = type_value; - inst->field_name = field_name; - inst->field_ptr = field_ptr; - - ir_ref_instruction(type_value, irb->current_basic_block); - ir_ref_instruction(field_name, irb->current_basic_block); - ir_ref_instruction(field_ptr, irb->current_basic_block); - - return &inst->base; -} - static IrInstGen *ir_build_field_parent_ptr_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *field_ptr, TypeStructField *field, ZigType *result_type) { @@ -4501,74 +2084,6 @@ static IrInstGen *ir_build_field_parent_ptr_gen(IrAnalyze *ira, IrInst *source_i return &inst->base; } -static IrInstSrc *ir_build_byte_offset_of(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *type_value, IrInstSrc *field_name) -{ - IrInstSrcByteOffsetOf *instruction = ir_build_instruction(irb, scope, source_node); - instruction->type_value = type_value; - instruction->field_name = field_name; - - ir_ref_instruction(type_value, irb->current_basic_block); - ir_ref_instruction(field_name, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstSrc *ir_build_bit_offset_of(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *type_value, IrInstSrc *field_name) -{ - IrInstSrcBitOffsetOf *instruction = ir_build_instruction(irb, scope, source_node); - instruction->type_value = type_value; - instruction->field_name = field_name; - - ir_ref_instruction(type_value, irb->current_basic_block); - ir_ref_instruction(field_name, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstSrc *ir_build_type_info(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *type_value) { - IrInstSrcTypeInfo *instruction = ir_build_instruction(irb, scope, source_node); - instruction->type_value = type_value; - - ir_ref_instruction(type_value, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstSrc *ir_build_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *type_info) { - IrInstSrcType *instruction = ir_build_instruction(irb, scope, source_node); - instruction->type_info = type_info; - - ir_ref_instruction(type_info, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstSrc *ir_build_set_eval_branch_quota(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *new_quota) -{ - IrInstSrcSetEvalBranchQuota *instruction = ir_build_instruction(irb, scope, source_node); - instruction->new_quota = new_quota; - - ir_ref_instruction(new_quota, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstSrc *ir_build_align_cast_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *align_bytes, IrInstSrc *target) -{ - IrInstSrcAlignCast *instruction = ir_build_instruction(irb, scope, source_node); - instruction->align_bytes = align_bytes; - instruction->target = target; - - ir_ref_instruction(align_bytes, irb->current_basic_block); - ir_ref_instruction(target, irb->current_basic_block); - - return &instruction->base; -} - static IrInstGen *ir_build_align_cast_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, IrInstGen *target, ZigType *result_type) { @@ -4581,69 +2096,6 @@ static IrInstGen *ir_build_align_cast_gen(IrAnalyze *ira, Scope *scope, AstNode return &instruction->base; } -static IrInstSrc *ir_build_resolve_result(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - ResultLoc *result_loc, IrInstSrc *ty) -{ - IrInstSrcResolveResult *instruction = ir_build_instruction(irb, scope, source_node); - instruction->result_loc = result_loc; - instruction->ty = ty; - - if (ty != nullptr) ir_ref_instruction(ty, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstSrc *ir_build_reset_result(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - ResultLoc *result_loc) -{ - IrInstSrcResetResult *instruction = ir_build_instruction(irb, scope, source_node); - instruction->result_loc = result_loc; - instruction->base.is_gen = true; - - return &instruction->base; -} - -static IrInstSrc *ir_build_set_align_stack(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *align_bytes) -{ - IrInstSrcSetAlignStack *instruction = ir_build_instruction(irb, scope, source_node); - instruction->align_bytes = align_bytes; - - ir_ref_instruction(align_bytes, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstSrc *ir_build_arg_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *fn_type, IrInstSrc *arg_index, bool allow_var) -{ - IrInstSrcArgType *instruction = heap::c_allocator.create(); - instruction->base.id = allow_var ? - IrInstSrcIdArgTypeAllowVarTrue : IrInstSrcIdArgTypeAllowVarFalse; - instruction->base.base.scope = scope; - instruction->base.base.source_node = source_node; - instruction->base.base.debug_id = exec_next_debug_id(irb->exec); - instruction->base.owner_bb = irb->current_basic_block; - ir_instruction_append(irb->current_basic_block, &instruction->base); - - instruction->fn_type = fn_type; - instruction->arg_index = arg_index; - - ir_ref_instruction(fn_type, irb->current_basic_block); - ir_ref_instruction(arg_index, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstSrc *ir_build_error_return_trace_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstErrorReturnTraceOptional optional) -{ - IrInstSrcErrorReturnTrace *inst = ir_build_instruction(irb, scope, source_node); - inst->optional = optional; - - return &inst->base; -} - static IrInstGen *ir_build_error_return_trace_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, IrInstErrorReturnTraceOptional optional, ZigType *result_type) { @@ -4654,39 +2106,6 @@ static IrInstGen *ir_build_error_return_trace_gen(IrAnalyze *ira, Scope *scope, return &inst->base; } -static IrInstSrc *ir_build_error_union(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *err_set, IrInstSrc *payload) -{ - IrInstSrcErrorUnion *instruction = ir_build_instruction(irb, scope, source_node); - instruction->err_set = err_set; - instruction->payload = payload; - - ir_ref_instruction(err_set, irb->current_basic_block); - ir_ref_instruction(payload, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstSrc *ir_build_atomic_rmw_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *operand_type, IrInstSrc *ptr, IrInstSrc *op, IrInstSrc *operand, - IrInstSrc *ordering) -{ - IrInstSrcAtomicRmw *instruction = ir_build_instruction(irb, scope, source_node); - instruction->operand_type = operand_type; - instruction->ptr = ptr; - instruction->op = op; - instruction->operand = operand; - instruction->ordering = ordering; - - ir_ref_instruction(operand_type, irb->current_basic_block); - ir_ref_instruction(ptr, irb->current_basic_block); - ir_ref_instruction(op, irb->current_basic_block); - ir_ref_instruction(operand, irb->current_basic_block); - ir_ref_instruction(ordering, irb->current_basic_block); - - return &instruction->base; -} - static IrInstGen *ir_build_atomic_rmw_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *ptr, IrInstGen *operand, AtomicRmwOp op, AtomicOrder ordering, ZigType *operand_type) { @@ -4703,21 +2122,6 @@ static IrInstGen *ir_build_atomic_rmw_gen(IrAnalyze *ira, IrInst *source_instr, return &instruction->base; } -static IrInstSrc *ir_build_atomic_load_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *operand_type, IrInstSrc *ptr, IrInstSrc *ordering) -{ - IrInstSrcAtomicLoad *instruction = ir_build_instruction(irb, scope, source_node); - instruction->operand_type = operand_type; - instruction->ptr = ptr; - instruction->ordering = ordering; - - ir_ref_instruction(operand_type, irb->current_basic_block); - ir_ref_instruction(ptr, irb->current_basic_block); - ir_ref_instruction(ordering, irb->current_basic_block); - - return &instruction->base; -} - static IrInstGen *ir_build_atomic_load_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *ptr, AtomicOrder ordering, ZigType *operand_type) { @@ -4732,23 +2136,6 @@ static IrInstGen *ir_build_atomic_load_gen(IrAnalyze *ira, IrInst *source_instr, return &instruction->base; } -static IrInstSrc *ir_build_atomic_store_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *operand_type, IrInstSrc *ptr, IrInstSrc *value, IrInstSrc *ordering) -{ - IrInstSrcAtomicStore *instruction = ir_build_instruction(irb, scope, source_node); - instruction->operand_type = operand_type; - instruction->ptr = ptr; - instruction->value = value; - instruction->ordering = ordering; - - ir_ref_instruction(operand_type, irb->current_basic_block); - ir_ref_instruction(ptr, irb->current_basic_block); - ir_ref_instruction(value, irb->current_basic_block); - ir_ref_instruction(ordering, irb->current_basic_block); - - return &instruction->base; -} - static IrInstGen *ir_build_atomic_store_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *ptr, IrInstGen *value, AtomicOrder ordering) { @@ -4764,77 +2151,6 @@ static IrInstGen *ir_build_atomic_store_gen(IrAnalyze *ira, IrInst *source_instr return &instruction->base; } -static IrInstSrc *ir_build_save_err_ret_addr_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { - IrInstSrcSaveErrRetAddr *inst = ir_build_instruction(irb, scope, source_node); - return &inst->base; -} - -static IrInstGen *ir_build_save_err_ret_addr_gen(IrAnalyze *ira, IrInst *source_instr) { - IrInstGenSaveErrRetAddr *inst = ir_build_inst_void(&ira->new_irb, - source_instr->scope, source_instr->source_node); - return &inst->base; -} - -static IrInstSrc *ir_build_add_implicit_return_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *value, ResultLocReturn *result_loc_ret) -{ - IrInstSrcAddImplicitReturnType *inst = ir_build_instruction(irb, scope, source_node); - inst->value = value; - inst->result_loc_ret = result_loc_ret; - - ir_ref_instruction(value, irb->current_basic_block); - - return &inst->base; -} - -static IrInstSrc *ir_build_has_decl(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *container, IrInstSrc *name) -{ - IrInstSrcHasDecl *instruction = ir_build_instruction(irb, scope, source_node); - instruction->container = container; - instruction->name = name; - - ir_ref_instruction(container, irb->current_basic_block); - ir_ref_instruction(name, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstSrc *ir_build_undeclared_identifier(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, Buf *name) { - IrInstSrcUndeclaredIdent *instruction = ir_build_instruction(irb, scope, source_node); - instruction->name = name; - - return &instruction->base; -} - -static IrInstSrc *ir_build_check_runtime_scope(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *scope_is_comptime, IrInstSrc *is_comptime) { - IrInstSrcCheckRuntimeScope *instruction = ir_build_instruction(irb, scope, source_node); - instruction->scope_is_comptime = scope_is_comptime; - instruction->is_comptime = is_comptime; - - ir_ref_instruction(scope_is_comptime, irb->current_basic_block); - ir_ref_instruction(is_comptime, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstSrc *ir_build_union_init_named_field(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *union_type, IrInstSrc *field_name, IrInstSrc *field_result_loc, IrInstSrc *result_loc) -{ - IrInstSrcUnionInitNamedField *instruction = ir_build_instruction(irb, scope, source_node); - instruction->union_type = union_type; - instruction->field_name = field_name; - instruction->field_result_loc = field_result_loc; - instruction->result_loc = result_loc; - - ir_ref_instruction(union_type, irb->current_basic_block); - ir_ref_instruction(field_name, irb->current_basic_block); - ir_ref_instruction(field_result_loc, irb->current_basic_block); - if (result_loc != nullptr) ir_ref_instruction(result_loc, irb->current_basic_block); - - return &instruction->base; -} - static IrInstGen *ir_build_vector_to_array(IrAnalyze *ira, IrInst *source_instruction, ZigType *result_type, IrInstGen *vector, IrInstGen *result_loc) @@ -4905,21 +2221,6 @@ static IrInstGen *ir_build_assert_non_null(IrAnalyze *ira, IrInst *source_instru return &instruction->base; } -static IrInstSrc *ir_build_alloca_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *align, const char *name_hint, IrInstSrc *is_comptime) -{ - IrInstSrcAlloca *instruction = ir_build_instruction(irb, scope, source_node); - instruction->base.is_gen = true; - instruction->align = align; - instruction->name_hint = name_hint; - instruction->is_comptime = is_comptime; - - if (align != nullptr) ir_ref_instruction(align, irb->current_basic_block); - if (is_comptime != nullptr) ir_ref_instruction(is_comptime, irb->current_basic_block); - - return &instruction->base; -} - static IrInstGenAlloca *ir_build_alloca_gen(IrAnalyze *ira, IrInst *source_instruction, uint32_t align, const char *name_hint) { @@ -4931,40 +2232,6 @@ static IrInstGenAlloca *ir_build_alloca_gen(IrAnalyze *ira, IrInst *source_instr return instruction; } -static IrInstSrc *ir_build_end_expr(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *value, ResultLoc *result_loc) -{ - IrInstSrcEndExpr *instruction = ir_build_instruction(irb, scope, source_node); - instruction->base.is_gen = true; - instruction->value = value; - instruction->result_loc = result_loc; - - ir_ref_instruction(value, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstSrcSuspendBegin *ir_build_suspend_begin_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { - return ir_build_instruction(irb, scope, source_node); -} - -static IrInstGen *ir_build_suspend_begin_gen(IrAnalyze *ira, IrInst *source_instr) { - IrInstGenSuspendBegin *inst = ir_build_inst_void(&ira->new_irb, - source_instr->scope, source_instr->source_node); - return &inst->base; -} - -static IrInstSrc *ir_build_suspend_finish_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrcSuspendBegin *begin) -{ - IrInstSrcSuspendFinish *inst = ir_build_instruction(irb, scope, source_node); - inst->begin = begin; - - ir_ref_instruction(&begin->base, irb->current_basic_block); - - return &inst->base; -} - static IrInstGen *ir_build_suspend_finish_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGenSuspendBegin *begin) { IrInstGenSuspendFinish *inst = ir_build_inst_void(&ira->new_irb, source_instr->scope, source_instr->source_node); @@ -4975,19 +2242,6 @@ static IrInstGen *ir_build_suspend_finish_gen(IrAnalyze *ira, IrInst *source_ins return &inst->base; } -static IrInstSrc *ir_build_await_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *frame, ResultLoc *result_loc, bool is_nosuspend) -{ - IrInstSrcAwait *instruction = ir_build_instruction(irb, scope, source_node); - instruction->frame = frame; - instruction->result_loc = result_loc; - instruction->is_nosuspend = is_nosuspend; - - ir_ref_instruction(frame, irb->current_basic_block); - - return &instruction->base; -} - static IrInstGenAwait *ir_build_await_gen(IrAnalyze *ira, IrInst *source_instruction, IrInstGen *frame, ZigType *result_type, IrInstGen *result_loc, bool is_nosuspend) { @@ -5004,15 +2258,6 @@ static IrInstGenAwait *ir_build_await_gen(IrAnalyze *ira, IrInst *source_instruc return instruction; } -static IrInstSrc *ir_build_resume_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *frame) { - IrInstSrcResume *instruction = ir_build_instruction(irb, scope, source_node); - instruction->frame = frame; - - ir_ref_instruction(frame, irb->current_basic_block); - - return &instruction->base; -} - static IrInstGen *ir_build_resume_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *frame) { IrInstGenResume *instruction = ir_build_inst_void(&ira->new_irb, source_instr->scope, source_instr->source_node); @@ -5023,18 +2268,6 @@ static IrInstGen *ir_build_resume_gen(IrAnalyze *ira, IrInst *source_instr, IrIn return &instruction->base; } -static IrInstSrcSpillBegin *ir_build_spill_begin_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *operand, SpillId spill_id) -{ - IrInstSrcSpillBegin *instruction = ir_build_instruction(irb, scope, source_node); - instruction->operand = operand; - instruction->spill_id = spill_id; - - ir_ref_instruction(operand, irb->current_basic_block); - - return instruction; -} - static IrInstGen *ir_build_spill_begin_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *operand, SpillId spill_id) { @@ -5048,17 +2281,6 @@ static IrInstGen *ir_build_spill_begin_gen(IrAnalyze *ira, IrInst *source_instr, return &instruction->base; } -static IrInstSrc *ir_build_spill_end_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrcSpillBegin *begin) -{ - IrInstSrcSpillEnd *instruction = ir_build_instruction(irb, scope, source_node); - instruction->begin = begin; - - ir_ref_instruction(&begin->base, irb->current_basic_block); - - return &instruction->base; -} - static IrInstGen *ir_build_spill_end_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGenSpillBegin *begin, ZigType *result_type) { @@ -5087,15 +2309,6 @@ static IrInstGen *ir_build_vector_extract_elem(IrAnalyze *ira, IrInst *source_in return &instruction->base; } -static IrInstSrc *ir_build_wasm_memory_size_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *index) { - IrInstSrcWasmMemorySize *instruction = ir_build_instruction(irb, scope, source_node); - instruction->index = index; - - ir_ref_instruction(index, irb->current_basic_block); - - return &instruction->base; -} - static IrInstGen *ir_build_wasm_memory_size_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *index) { IrInstGenWasmMemorySize *instruction = ir_build_inst_gen(&ira->new_irb, source_instr->scope, source_instr->source_node); @@ -5107,17 +2320,6 @@ static IrInstGen *ir_build_wasm_memory_size_gen(IrAnalyze *ira, IrInst *source_i return &instruction->base; } -static IrInstSrc *ir_build_wasm_memory_grow_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *index, IrInstSrc *delta) { - IrInstSrcWasmMemoryGrow *instruction = ir_build_instruction(irb, scope, source_node); - instruction->index = index; - instruction->delta = delta; - - ir_ref_instruction(index, irb->current_basic_block); - ir_ref_instruction(delta, irb->current_basic_block); - - return &instruction->base; -} - static IrInstGen *ir_build_wasm_memory_grow_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *index, IrInstGen *delta) { IrInstGenWasmMemoryGrow *instruction = ir_build_inst_gen(&ira->new_irb, source_instr->scope, source_instr->source_node); @@ -5131,3676 +2333,6 @@ static IrInstGen *ir_build_wasm_memory_grow_gen(IrAnalyze *ira, IrInst *source_i return &instruction->base; } -static IrInstSrc *ir_build_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { - IrInstSrcSrc *instruction = ir_build_instruction(irb, scope, source_node); - - return &instruction->base; -} - -static void ir_count_defers(IrBuilderSrc *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { - results[ReturnKindUnconditional] = 0; - results[ReturnKindError] = 0; - - Scope *scope = inner_scope; - - while (scope != outer_scope) { - assert(scope); - switch (scope->id) { - case ScopeIdDefer: { - AstNode *defer_node = scope->source_node; - assert(defer_node->type == NodeTypeDefer); - ReturnKind defer_kind = defer_node->data.defer.kind; - results[defer_kind] += 1; - scope = scope->parent; - continue; - } - case ScopeIdDecls: - case ScopeIdFnDef: - return; - case ScopeIdBlock: - case ScopeIdVarDecl: - case ScopeIdLoop: - case ScopeIdSuspend: - case ScopeIdCompTime: - case ScopeIdNoSuspend: - case ScopeIdRuntime: - case ScopeIdTypeOf: - case ScopeIdExpr: - scope = scope->parent; - continue; - case ScopeIdDeferExpr: - case ScopeIdCImport: - zig_unreachable(); - } - } -} - -static IrInstSrc *ir_mark_gen(IrInstSrc *instruction) { - instruction->is_gen = true; - return instruction; -} - -static bool ir_gen_defers_for_block(IrBuilderSrc *irb, Scope *inner_scope, Scope *outer_scope, bool *is_noreturn, IrInstSrc *err_value) { - Scope *scope = inner_scope; - if (is_noreturn != nullptr) *is_noreturn = false; - while (scope != outer_scope) { - if (!scope) - return true; - - switch (scope->id) { - case ScopeIdDefer: { - AstNode *defer_node = scope->source_node; - assert(defer_node->type == NodeTypeDefer); - ReturnKind defer_kind = defer_node->data.defer.kind; - AstNode *defer_expr_node = defer_node->data.defer.expr; - AstNode *defer_var_node = defer_node->data.defer.err_payload; - - if (defer_kind == ReturnKindError && err_value == nullptr) { - // This is an `errdefer` but we're generating code for a - // `return` that doesn't return an error, skip it - scope = scope->parent; - continue; - } - - Scope *defer_expr_scope = defer_node->data.defer.expr_scope; - if (defer_var_node != nullptr) { - assert(defer_kind == ReturnKindError); - assert(defer_var_node->type == NodeTypeSymbol); - Buf *var_name = defer_var_node->data.symbol_expr.symbol; - - if (defer_expr_node->type == NodeTypeUnreachable) { - add_node_error(irb->codegen, defer_var_node, - buf_sprintf("unused variable: '%s'", buf_ptr(var_name))); - return false; - } - - IrInstSrc *is_comptime; - if (ir_should_inline(irb->exec, defer_expr_scope)) { - is_comptime = ir_build_const_bool(irb, defer_expr_scope, - defer_expr_node, true); - } else { - is_comptime = ir_build_test_comptime(irb, defer_expr_scope, - defer_expr_node, err_value); - } - - ZigVar *err_var = ir_create_var(irb, defer_var_node, defer_expr_scope, - var_name, true, true, false, is_comptime); - build_decl_var_and_init(irb, defer_expr_scope, defer_var_node, err_var, err_value, - buf_ptr(var_name), is_comptime); - - defer_expr_scope = err_var->child_scope; - } - - IrInstSrc *defer_expr_value = ir_gen_node(irb, defer_expr_node, defer_expr_scope); - if (defer_expr_value == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - - if (defer_expr_value->is_noreturn) { - if (is_noreturn != nullptr) *is_noreturn = true; - } else { - ir_mark_gen(ir_build_check_statement_is_void(irb, defer_expr_scope, defer_expr_node, - defer_expr_value)); - } - scope = scope->parent; - continue; - } - case ScopeIdDecls: - case ScopeIdFnDef: - return true; - case ScopeIdBlock: - case ScopeIdVarDecl: - case ScopeIdLoop: - case ScopeIdSuspend: - case ScopeIdCompTime: - case ScopeIdNoSuspend: - case ScopeIdRuntime: - case ScopeIdTypeOf: - case ScopeIdExpr: - scope = scope->parent; - continue; - case ScopeIdDeferExpr: - case ScopeIdCImport: - zig_unreachable(); - } - } - return true; -} - -static void ir_set_cursor_at_end_gen(IrBuilderGen *irb, IrBasicBlockGen *basic_block) { - assert(basic_block); - irb->current_basic_block = basic_block; -} - -static void ir_set_cursor_at_end(IrBuilderSrc *irb, IrBasicBlockSrc *basic_block) { - assert(basic_block); - irb->current_basic_block = basic_block; -} - -static void ir_append_basic_block_gen(IrBuilderGen *irb, IrBasicBlockGen *bb) { - assert(!bb->already_appended); - bb->already_appended = true; - irb->exec->basic_block_list.append(bb); -} - -static void ir_set_cursor_at_end_and_append_block_gen(IrBuilderGen *irb, IrBasicBlockGen *basic_block) { - ir_append_basic_block_gen(irb, basic_block); - ir_set_cursor_at_end_gen(irb, basic_block); -} - -static void ir_set_cursor_at_end_and_append_block(IrBuilderSrc *irb, IrBasicBlockSrc *basic_block) { - basic_block->index = irb->exec->basic_block_list.length; - irb->exec->basic_block_list.append(basic_block); - ir_set_cursor_at_end(irb, basic_block); -} - -static ScopeSuspend *get_scope_suspend(Scope *scope) { - while (scope) { - if (scope->id == ScopeIdSuspend) - return (ScopeSuspend *)scope; - if (scope->id == ScopeIdFnDef) - return nullptr; - - scope = scope->parent; - } - return nullptr; -} - -static ScopeDeferExpr *get_scope_defer_expr(Scope *scope) { - while (scope) { - if (scope->id == ScopeIdDeferExpr) - return (ScopeDeferExpr *)scope; - if (scope->id == ScopeIdFnDef) - return nullptr; - - scope = scope->parent; - } - return nullptr; -} - -static IrInstSrc *ir_gen_return(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { - assert(node->type == NodeTypeReturnExpr); - - ScopeDeferExpr *scope_defer_expr = get_scope_defer_expr(scope); - if (scope_defer_expr) { - if (!scope_defer_expr->reported_err) { - add_node_error(irb->codegen, node, buf_sprintf("cannot return from defer expression")); - scope_defer_expr->reported_err = true; - } - return irb->codegen->invalid_inst_src; - } - - Scope *outer_scope = irb->exec->begin_scope; - - AstNode *expr_node = node->data.return_expr.expr; - switch (node->data.return_expr.kind) { - case ReturnKindUnconditional: - { - ResultLocReturn *result_loc_ret = heap::c_allocator.create(); - result_loc_ret->base.id = ResultLocIdReturn; - ir_build_reset_result(irb, scope, node, &result_loc_ret->base); - - IrInstSrc *return_value; - if (expr_node) { - // Temporarily set this so that if we return a type it gets the name of the function - ZigFn *prev_name_fn = irb->exec->name_fn; - irb->exec->name_fn = exec_fn_entry(irb->exec); - return_value = ir_gen_node_extra(irb, expr_node, scope, LValNone, &result_loc_ret->base); - irb->exec->name_fn = prev_name_fn; - if (return_value == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - } else { - return_value = ir_build_const_void(irb, scope, node); - ir_build_end_expr(irb, scope, node, return_value, &result_loc_ret->base); - } - - ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, node, return_value, result_loc_ret)); - - size_t defer_counts[2]; - ir_count_defers(irb, scope, outer_scope, defer_counts); - bool have_err_defers = defer_counts[ReturnKindError] > 0; - if (!have_err_defers && !irb->codegen->have_err_ret_tracing) { - // only generate unconditional defers - if (!ir_gen_defers_for_block(irb, scope, outer_scope, nullptr, nullptr)) - return irb->codegen->invalid_inst_src; - IrInstSrc *result = ir_build_return_src(irb, scope, node, nullptr); - result_loc_ret->base.source_instruction = result; - return result; - } - bool should_inline = ir_should_inline(irb->exec, scope); - - IrBasicBlockSrc *err_block = ir_create_basic_block(irb, scope, "ErrRetErr"); - IrBasicBlockSrc *ok_block = ir_create_basic_block(irb, scope, "ErrRetOk"); - - IrInstSrc *is_err = ir_build_test_err_src(irb, scope, node, return_value, false, true); - - IrInstSrc *is_comptime; - if (should_inline) { - is_comptime = ir_build_const_bool(irb, scope, node, should_inline); - } else { - is_comptime = ir_build_test_comptime(irb, scope, node, is_err); - } - - ir_mark_gen(ir_build_cond_br(irb, scope, node, is_err, err_block, ok_block, is_comptime)); - IrBasicBlockSrc *ret_stmt_block = ir_create_basic_block(irb, scope, "RetStmt"); - - ir_set_cursor_at_end_and_append_block(irb, err_block); - if (!ir_gen_defers_for_block(irb, scope, outer_scope, nullptr, return_value)) - return irb->codegen->invalid_inst_src; - if (irb->codegen->have_err_ret_tracing && !should_inline) { - ir_build_save_err_ret_addr_src(irb, scope, node); - } - ir_build_br(irb, scope, node, ret_stmt_block, is_comptime); - - ir_set_cursor_at_end_and_append_block(irb, ok_block); - if (!ir_gen_defers_for_block(irb, scope, outer_scope, nullptr, nullptr)) - return irb->codegen->invalid_inst_src; - ir_build_br(irb, scope, node, ret_stmt_block, is_comptime); - - ir_set_cursor_at_end_and_append_block(irb, ret_stmt_block); - IrInstSrc *result = ir_build_return_src(irb, scope, node, nullptr); - result_loc_ret->base.source_instruction = result; - return result; - } - case ReturnKindError: - { - assert(expr_node); - IrInstSrc *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr); - if (err_union_ptr == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - IrInstSrc *is_err_val = ir_build_test_err_src(irb, scope, node, err_union_ptr, true, false); - - IrBasicBlockSrc *return_block = ir_create_basic_block(irb, scope, "ErrRetReturn"); - IrBasicBlockSrc *continue_block = ir_create_basic_block(irb, scope, "ErrRetContinue"); - IrInstSrc *is_comptime; - bool should_inline = ir_should_inline(irb->exec, scope); - if (should_inline) { - is_comptime = ir_build_const_bool(irb, scope, node, true); - } else { - is_comptime = ir_build_test_comptime(irb, scope, node, is_err_val); - } - ir_mark_gen(ir_build_cond_br(irb, scope, node, is_err_val, return_block, continue_block, is_comptime)); - - ir_set_cursor_at_end_and_append_block(irb, return_block); - IrInstSrc *err_val_ptr = ir_build_unwrap_err_code_src(irb, scope, node, err_union_ptr); - IrInstSrc *err_val = ir_build_load_ptr(irb, scope, node, err_val_ptr); - ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, node, err_val, nullptr)); - IrInstSrcSpillBegin *spill_begin = ir_build_spill_begin_src(irb, scope, node, err_val, - SpillIdRetErrCode); - ResultLocReturn *result_loc_ret = heap::c_allocator.create(); - result_loc_ret->base.id = ResultLocIdReturn; - ir_build_reset_result(irb, scope, node, &result_loc_ret->base); - ir_build_end_expr(irb, scope, node, err_val, &result_loc_ret->base); - - bool is_noreturn = false; - if (!ir_gen_defers_for_block(irb, scope, outer_scope, &is_noreturn, err_val)) { - return irb->codegen->invalid_inst_src; - } - if (!is_noreturn) { - if (irb->codegen->have_err_ret_tracing && !should_inline) { - ir_build_save_err_ret_addr_src(irb, scope, node); - } - err_val = ir_build_spill_end_src(irb, scope, node, spill_begin); - IrInstSrc *ret_inst = ir_build_return_src(irb, scope, node, err_val); - result_loc_ret->base.source_instruction = ret_inst; - } - - ir_set_cursor_at_end_and_append_block(irb, continue_block); - IrInstSrc *unwrapped_ptr = ir_build_unwrap_err_payload_src(irb, scope, node, err_union_ptr, false, false); - if (lval == LValPtr) - return unwrapped_ptr; - else - return ir_expr_wrap(irb, scope, ir_build_load_ptr(irb, scope, node, unwrapped_ptr), result_loc); - } - } - zig_unreachable(); -} - -static ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_scope, - Buf *name, bool src_is_const, bool gen_is_const, bool is_shadowable, IrInstSrc *is_comptime, - bool skip_name_check) -{ - ZigVar *variable_entry = heap::c_allocator.create(); - variable_entry->parent_scope = parent_scope; - variable_entry->shadowable = is_shadowable; - variable_entry->is_comptime = is_comptime; - variable_entry->src_arg_index = SIZE_MAX; - variable_entry->const_value = codegen->pass1_arena->create(); - - if (is_comptime != nullptr) { - is_comptime->base.ref_count += 1; - } - - if (name) { - variable_entry->name = strdup(buf_ptr(name)); - - if (!skip_name_check) { - ZigVar *existing_var = find_variable(codegen, parent_scope, name, nullptr); - if (existing_var && !existing_var->shadowable) { - if (existing_var->var_type == nullptr || !type_is_invalid(existing_var->var_type)) { - ErrorMsg *msg = add_node_error(codegen, node, - buf_sprintf("redeclaration of variable '%s'", buf_ptr(name))); - add_error_note(codegen, msg, existing_var->decl_node, buf_sprintf("previous declaration is here")); - } - variable_entry->var_type = codegen->builtin_types.entry_invalid; - } else { - ZigType *type; - if (get_primitive_type(codegen, name, &type) != ErrorPrimitiveTypeNotFound) { - add_node_error(codegen, node, - buf_sprintf("variable shadows primitive type '%s'", buf_ptr(name))); - variable_entry->var_type = codegen->builtin_types.entry_invalid; - } else { - Tld *tld = find_decl(codegen, parent_scope, name); - if (tld != nullptr) { - bool want_err_msg = true; - if (tld->id == TldIdVar) { - ZigVar *var = reinterpret_cast(tld)->var; - if (var != nullptr && var->var_type != nullptr && type_is_invalid(var->var_type)) { - want_err_msg = false; - } - } - if (want_err_msg) { - ErrorMsg *msg = add_node_error(codegen, node, - buf_sprintf("redefinition of '%s'", buf_ptr(name))); - add_error_note(codegen, msg, tld->source_node, buf_sprintf("previous definition is here")); - } - variable_entry->var_type = codegen->builtin_types.entry_invalid; - } - } - } - } - } else { - assert(is_shadowable); - // TODO make this name not actually be in scope. user should be able to make a variable called "_anon" - // might already be solved, let's just make sure it has test coverage - // maybe we put a prefix on this so the debug info doesn't clobber user debug info for same named variables - variable_entry->name = "_anon"; - } - - variable_entry->src_is_const = src_is_const; - variable_entry->gen_is_const = gen_is_const; - variable_entry->decl_node = node; - variable_entry->child_scope = create_var_scope(codegen, node, parent_scope, variable_entry); - - return variable_entry; -} - -// Set name to nullptr to make the variable anonymous (not visible to programmer). -// After you call this function var->child_scope has the variable in scope -static ZigVar *ir_create_var(IrBuilderSrc *irb, AstNode *node, Scope *scope, Buf *name, - bool src_is_const, bool gen_is_const, bool is_shadowable, IrInstSrc *is_comptime) -{ - bool is_underscored = name ? buf_eql_str(name, "_") : false; - ZigVar *var = create_local_var(irb->codegen, node, scope, - (is_underscored ? nullptr : name), src_is_const, gen_is_const, - (is_underscored ? true : is_shadowable), is_comptime, false); - assert(var->child_scope); - return var; -} - -static ResultLocPeer *create_peer_result(ResultLocPeerParent *peer_parent) { - ResultLocPeer *result = heap::c_allocator.create(); - result->base.id = ResultLocIdPeer; - result->base.source_instruction = peer_parent->base.source_instruction; - result->parent = peer_parent; - result->base.allow_write_through_const = peer_parent->parent->allow_write_through_const; - return result; -} - -static bool is_duplicate_label(CodeGen *g, Scope *scope, AstNode *node, Buf *name) { - if (name == nullptr) return false; - - for (;;) { - if (scope == nullptr || scope->id == ScopeIdFnDef) { - break; - } else if (scope->id == ScopeIdBlock || scope->id == ScopeIdLoop) { - Buf *this_block_name = scope->id == ScopeIdBlock ? ((ScopeBlock *)scope)->name : ((ScopeLoop *)scope)->name; - if (this_block_name != nullptr && buf_eql_buf(name, this_block_name)) { - ErrorMsg *msg = add_node_error(g, node, buf_sprintf("redeclaration of label '%s'", buf_ptr(name))); - add_error_note(g, msg, scope->source_node, buf_sprintf("previous declaration is here")); - return true; - } - } - scope = scope->parent; - } - return false; -} - -static IrInstSrc *ir_gen_block(IrBuilderSrc *irb, Scope *parent_scope, AstNode *block_node, LVal lval, - ResultLoc *result_loc) -{ - assert(block_node->type == NodeTypeBlock); - - ZigList incoming_values = {0}; - ZigList incoming_blocks = {0}; - - if (is_duplicate_label(irb->codegen, parent_scope, block_node, block_node->data.block.name)) - return irb->codegen->invalid_inst_src; - - ScopeBlock *scope_block = create_block_scope(irb->codegen, block_node, parent_scope); - - Scope *outer_block_scope = &scope_block->base; - Scope *child_scope = outer_block_scope; - - ZigFn *fn_entry = scope_fn_entry(parent_scope); - if (fn_entry && fn_entry->child_scope == parent_scope) { - fn_entry->def_scope = scope_block; - } - - if (block_node->data.block.statements.length == 0) { - if (scope_block->name != nullptr) { - add_node_error(irb->codegen, block_node, buf_sprintf("unused block label")); - } - // {} - return ir_lval_wrap(irb, parent_scope, ir_build_const_void(irb, child_scope, block_node), lval, result_loc); - } - - if (block_node->data.block.name != nullptr) { - scope_block->lval = lval; - scope_block->incoming_blocks = &incoming_blocks; - scope_block->incoming_values = &incoming_values; - scope_block->end_block = ir_create_basic_block(irb, parent_scope, "BlockEnd"); - scope_block->is_comptime = ir_build_const_bool(irb, parent_scope, block_node, - ir_should_inline(irb->exec, parent_scope)); - - scope_block->peer_parent = heap::c_allocator.create(); - scope_block->peer_parent->base.id = ResultLocIdPeerParent; - scope_block->peer_parent->base.source_instruction = scope_block->is_comptime; - scope_block->peer_parent->base.allow_write_through_const = result_loc->allow_write_through_const; - scope_block->peer_parent->end_bb = scope_block->end_block; - scope_block->peer_parent->is_comptime = scope_block->is_comptime; - scope_block->peer_parent->parent = result_loc; - ir_build_reset_result(irb, parent_scope, block_node, &scope_block->peer_parent->base); - } - - bool is_continuation_unreachable = false; - bool found_invalid_inst = false; - IrInstSrc *noreturn_return_value = nullptr; - for (size_t i = 0; i < block_node->data.block.statements.length; i += 1) { - AstNode *statement_node = block_node->data.block.statements.at(i); - - IrInstSrc *statement_value = ir_gen_node(irb, statement_node, child_scope); - if (statement_value == irb->codegen->invalid_inst_src) { - // keep generating all the elements of the block in case of error, - // we want to collect other compile errors - found_invalid_inst = true; - continue; - } - - is_continuation_unreachable = instr_is_unreachable(statement_value); - if (is_continuation_unreachable) { - // keep the last noreturn statement value around in case we need to return it - noreturn_return_value = statement_value; - } - // This logic must be kept in sync with - // [STMT_EXPR_TEST_THING] <--- (search this token) - if (statement_node->type == NodeTypeDefer) { - // defer starts a new scope - child_scope = statement_node->data.defer.child_scope; - assert(child_scope); - } else if (statement_value->id == IrInstSrcIdDeclVar) { - // variable declarations start a new scope - IrInstSrcDeclVar *decl_var_instruction = (IrInstSrcDeclVar *)statement_value; - child_scope = decl_var_instruction->var->child_scope; - } else if (!is_continuation_unreachable) { - // this statement's value must be void - ir_mark_gen(ir_build_check_statement_is_void(irb, child_scope, statement_node, statement_value)); - } - } - - if (scope_block->name != nullptr && scope_block->name_used == false) { - add_node_error(irb->codegen, block_node, buf_sprintf("unused block label")); - } - - if (found_invalid_inst) - return irb->codegen->invalid_inst_src; - - if (is_continuation_unreachable) { - assert(noreturn_return_value != nullptr); - if (block_node->data.block.name == nullptr || incoming_blocks.length == 0) { - return noreturn_return_value; - } - - if (scope_block->peer_parent != nullptr && scope_block->peer_parent->peers.length != 0) { - scope_block->peer_parent->peers.last()->next_bb = scope_block->end_block; - } - ir_set_cursor_at_end_and_append_block(irb, scope_block->end_block); - IrInstSrc *phi = ir_build_phi(irb, parent_scope, block_node, incoming_blocks.length, - incoming_blocks.items, incoming_values.items, scope_block->peer_parent); - return ir_expr_wrap(irb, parent_scope, phi, result_loc); - } else { - incoming_blocks.append(irb->current_basic_block); - IrInstSrc *else_expr_result = ir_mark_gen(ir_build_const_void(irb, parent_scope, block_node)); - - if (scope_block->peer_parent != nullptr) { - ResultLocPeer *peer_result = create_peer_result(scope_block->peer_parent); - scope_block->peer_parent->peers.append(peer_result); - ir_build_end_expr(irb, parent_scope, block_node, else_expr_result, &peer_result->base); - - if (scope_block->peer_parent->peers.length != 0) { - scope_block->peer_parent->peers.last()->next_bb = scope_block->end_block; - } - } - - incoming_values.append(else_expr_result); - } - - bool is_return_from_fn = block_node == irb->main_block_node; - if (!is_return_from_fn) { - if (!ir_gen_defers_for_block(irb, child_scope, outer_block_scope, nullptr, nullptr)) - return irb->codegen->invalid_inst_src; - } - - IrInstSrc *result; - if (block_node->data.block.name != nullptr) { - ir_mark_gen(ir_build_br(irb, parent_scope, block_node, scope_block->end_block, scope_block->is_comptime)); - ir_set_cursor_at_end_and_append_block(irb, scope_block->end_block); - IrInstSrc *phi = ir_build_phi(irb, parent_scope, block_node, incoming_blocks.length, - incoming_blocks.items, incoming_values.items, scope_block->peer_parent); - result = ir_expr_wrap(irb, parent_scope, phi, result_loc); - } else { - IrInstSrc *void_inst = ir_mark_gen(ir_build_const_void(irb, child_scope, block_node)); - result = ir_lval_wrap(irb, parent_scope, void_inst, lval, result_loc); - } - if (!is_return_from_fn) - return result; - - // no need for save_err_ret_addr because this cannot return error - // only generate unconditional defers - - ir_mark_gen(ir_build_add_implicit_return_type(irb, child_scope, block_node, result, nullptr)); - ResultLocReturn *result_loc_ret = heap::c_allocator.create(); - result_loc_ret->base.id = ResultLocIdReturn; - ir_build_reset_result(irb, parent_scope, block_node, &result_loc_ret->base); - ir_mark_gen(ir_build_end_expr(irb, parent_scope, block_node, result, &result_loc_ret->base)); - if (!ir_gen_defers_for_block(irb, child_scope, outer_block_scope, nullptr, nullptr)) - return irb->codegen->invalid_inst_src; - return ir_mark_gen(ir_build_return_src(irb, child_scope, result->base.source_node, result)); -} - -static IrInstSrc *ir_gen_bin_op_id(IrBuilderSrc *irb, Scope *scope, AstNode *node, IrBinOp op_id) { - Scope *inner_scope = scope; - if (op_id == IrBinOpArrayCat || op_id == IrBinOpArrayMult) { - inner_scope = create_comptime_scope(irb->codegen, node, scope); - } - - IrInstSrc *op1 = ir_gen_node(irb, node->data.bin_op_expr.op1, inner_scope); - IrInstSrc *op2 = ir_gen_node(irb, node->data.bin_op_expr.op2, inner_scope); - - if (op1 == irb->codegen->invalid_inst_src || op2 == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - - return ir_build_bin_op(irb, scope, node, op_id, op1, op2, true); -} - -static IrInstSrc *ir_gen_merge_err_sets(IrBuilderSrc *irb, Scope *scope, AstNode *node) { - IrInstSrc *op1 = ir_gen_node(irb, node->data.bin_op_expr.op1, scope); - IrInstSrc *op2 = ir_gen_node(irb, node->data.bin_op_expr.op2, scope); - - if (op1 == irb->codegen->invalid_inst_src || op2 == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - - // TODO only pass type_name when the || operator is the top level AST node in the var decl expr - Buf bare_name = BUF_INIT; - Buf *type_name = get_anon_type_name(irb->codegen, irb->exec, "error", scope, node, &bare_name); - - return ir_build_merge_err_sets(irb, scope, node, op1, op2, type_name); -} - -static IrInstSrc *ir_gen_assign(IrBuilderSrc *irb, Scope *scope, AstNode *node) { - IrInstSrc *lvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op1, scope, LValAssign, nullptr); - if (lvalue == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - - ResultLocInstruction *result_loc_inst = heap::c_allocator.create(); - result_loc_inst->base.id = ResultLocIdInstruction; - result_loc_inst->base.source_instruction = lvalue; - ir_ref_instruction(lvalue, irb->current_basic_block); - ir_build_reset_result(irb, scope, node, &result_loc_inst->base); - - IrInstSrc *rvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op2, scope, LValNone, - &result_loc_inst->base); - if (rvalue == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - - return ir_build_const_void(irb, scope, node); -} - -static IrInstSrc *ir_gen_assign_op(IrBuilderSrc *irb, Scope *scope, AstNode *node, IrBinOp op_id) { - IrInstSrc *lvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op1, scope, LValAssign, nullptr); - if (lvalue == irb->codegen->invalid_inst_src) - return lvalue; - IrInstSrc *op1 = ir_build_load_ptr(irb, scope, node->data.bin_op_expr.op1, lvalue); - IrInstSrc *op2 = ir_gen_node(irb, node->data.bin_op_expr.op2, scope); - if (op2 == irb->codegen->invalid_inst_src) - return op2; - IrInstSrc *result = ir_build_bin_op(irb, scope, node, op_id, op1, op2, true); - ir_build_store_ptr(irb, scope, node, lvalue, result); - return ir_build_const_void(irb, scope, node); -} - -static IrInstSrc *ir_gen_bool_or(IrBuilderSrc *irb, Scope *scope, AstNode *node) { - assert(node->type == NodeTypeBinOpExpr); - - IrInstSrc *val1 = ir_gen_node(irb, node->data.bin_op_expr.op1, scope); - if (val1 == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - IrBasicBlockSrc *post_val1_block = irb->current_basic_block; - - IrInstSrc *is_comptime; - if (ir_should_inline(irb->exec, scope)) { - is_comptime = ir_build_const_bool(irb, scope, node, true); - } else { - is_comptime = ir_build_test_comptime(irb, scope, node, val1); - } - - // block for when val1 == false - IrBasicBlockSrc *false_block = ir_create_basic_block(irb, scope, "BoolOrFalse"); - // block for when val1 == true (don't even evaluate the second part) - IrBasicBlockSrc *true_block = ir_create_basic_block(irb, scope, "BoolOrTrue"); - - ir_build_cond_br(irb, scope, node, val1, true_block, false_block, is_comptime); - - ir_set_cursor_at_end_and_append_block(irb, false_block); - IrInstSrc *val2 = ir_gen_node(irb, node->data.bin_op_expr.op2, scope); - if (val2 == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - IrBasicBlockSrc *post_val2_block = irb->current_basic_block; - - ir_build_br(irb, scope, node, true_block, is_comptime); - - ir_set_cursor_at_end_and_append_block(irb, true_block); - - IrInstSrc **incoming_values = heap::c_allocator.allocate(2); - incoming_values[0] = val1; - incoming_values[1] = val2; - IrBasicBlockSrc **incoming_blocks = heap::c_allocator.allocate(2); - incoming_blocks[0] = post_val1_block; - incoming_blocks[1] = post_val2_block; - - return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, nullptr); -} - -static IrInstSrc *ir_gen_bool_and(IrBuilderSrc *irb, Scope *scope, AstNode *node) { - assert(node->type == NodeTypeBinOpExpr); - - IrInstSrc *val1 = ir_gen_node(irb, node->data.bin_op_expr.op1, scope); - if (val1 == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - IrBasicBlockSrc *post_val1_block = irb->current_basic_block; - - IrInstSrc *is_comptime; - if (ir_should_inline(irb->exec, scope)) { - is_comptime = ir_build_const_bool(irb, scope, node, true); - } else { - is_comptime = ir_build_test_comptime(irb, scope, node, val1); - } - - // block for when val1 == true - IrBasicBlockSrc *true_block = ir_create_basic_block(irb, scope, "BoolAndTrue"); - // block for when val1 == false (don't even evaluate the second part) - IrBasicBlockSrc *false_block = ir_create_basic_block(irb, scope, "BoolAndFalse"); - - ir_build_cond_br(irb, scope, node, val1, true_block, false_block, is_comptime); - - ir_set_cursor_at_end_and_append_block(irb, true_block); - IrInstSrc *val2 = ir_gen_node(irb, node->data.bin_op_expr.op2, scope); - if (val2 == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - IrBasicBlockSrc *post_val2_block = irb->current_basic_block; - - ir_build_br(irb, scope, node, false_block, is_comptime); - - ir_set_cursor_at_end_and_append_block(irb, false_block); - - IrInstSrc **incoming_values = heap::c_allocator.allocate(2); - incoming_values[0] = val1; - incoming_values[1] = val2; - IrBasicBlockSrc **incoming_blocks = heap::c_allocator.allocate(2); - incoming_blocks[0] = post_val1_block; - incoming_blocks[1] = post_val2_block; - - return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, nullptr); -} - -static ResultLocPeerParent *ir_build_result_peers(IrBuilderSrc *irb, IrInstSrc *cond_br_inst, - IrBasicBlockSrc *end_block, ResultLoc *parent, IrInstSrc *is_comptime) -{ - ResultLocPeerParent *peer_parent = heap::c_allocator.create(); - peer_parent->base.id = ResultLocIdPeerParent; - peer_parent->base.source_instruction = cond_br_inst; - peer_parent->base.allow_write_through_const = parent->allow_write_through_const; - peer_parent->end_bb = end_block; - peer_parent->is_comptime = is_comptime; - peer_parent->parent = parent; - - IrInstSrc *popped_inst = irb->current_basic_block->instruction_list.pop(); - ir_assert(popped_inst == cond_br_inst, &cond_br_inst->base); - - ir_build_reset_result(irb, cond_br_inst->base.scope, cond_br_inst->base.source_node, &peer_parent->base); - irb->current_basic_block->instruction_list.append(popped_inst); - - return peer_parent; -} - -static ResultLocPeerParent *ir_build_binary_result_peers(IrBuilderSrc *irb, IrInstSrc *cond_br_inst, - IrBasicBlockSrc *else_block, IrBasicBlockSrc *end_block, ResultLoc *parent, IrInstSrc *is_comptime) -{ - ResultLocPeerParent *peer_parent = ir_build_result_peers(irb, cond_br_inst, end_block, parent, is_comptime); - - peer_parent->peers.append(create_peer_result(peer_parent)); - peer_parent->peers.last()->next_bb = else_block; - - peer_parent->peers.append(create_peer_result(peer_parent)); - peer_parent->peers.last()->next_bb = end_block; - - return peer_parent; -} - -static IrInstSrc *ir_gen_orelse(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node, LVal lval, - ResultLoc *result_loc) -{ - assert(node->type == NodeTypeBinOpExpr); - - AstNode *op1_node = node->data.bin_op_expr.op1; - AstNode *op2_node = node->data.bin_op_expr.op2; - - IrInstSrc *maybe_ptr = ir_gen_node_extra(irb, op1_node, parent_scope, LValPtr, nullptr); - if (maybe_ptr == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - - IrInstSrc *maybe_val = ir_build_load_ptr(irb, parent_scope, node, maybe_ptr); - IrInstSrc *is_non_null = ir_build_test_non_null_src(irb, parent_scope, node, maybe_val); - - IrInstSrc *is_comptime; - if (ir_should_inline(irb->exec, parent_scope)) { - is_comptime = ir_build_const_bool(irb, parent_scope, node, true); - } else { - is_comptime = ir_build_test_comptime(irb, parent_scope, node, is_non_null); - } - - IrBasicBlockSrc *ok_block = ir_create_basic_block(irb, parent_scope, "OptionalNonNull"); - IrBasicBlockSrc *null_block = ir_create_basic_block(irb, parent_scope, "OptionalNull"); - IrBasicBlockSrc *end_block = ir_create_basic_block(irb, parent_scope, "OptionalEnd"); - IrInstSrc *cond_br_inst = ir_build_cond_br(irb, parent_scope, node, is_non_null, ok_block, null_block, is_comptime); - - ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, ok_block, end_block, - result_loc, is_comptime); - - ir_set_cursor_at_end_and_append_block(irb, null_block); - IrInstSrc *null_result = ir_gen_node_extra(irb, op2_node, parent_scope, LValNone, - &peer_parent->peers.at(0)->base); - if (null_result == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - IrBasicBlockSrc *after_null_block = irb->current_basic_block; - if (!instr_is_unreachable(null_result)) - ir_mark_gen(ir_build_br(irb, parent_scope, node, end_block, is_comptime)); - - ir_set_cursor_at_end_and_append_block(irb, ok_block); - IrInstSrc *unwrapped_ptr = ir_build_optional_unwrap_ptr(irb, parent_scope, node, maybe_ptr, false); - IrInstSrc *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr); - ir_build_end_expr(irb, parent_scope, node, unwrapped_payload, &peer_parent->peers.at(1)->base); - IrBasicBlockSrc *after_ok_block = irb->current_basic_block; - ir_build_br(irb, parent_scope, node, end_block, is_comptime); - - ir_set_cursor_at_end_and_append_block(irb, end_block); - IrInstSrc **incoming_values = heap::c_allocator.allocate(2); - incoming_values[0] = null_result; - incoming_values[1] = unwrapped_payload; - IrBasicBlockSrc **incoming_blocks = heap::c_allocator.allocate(2); - incoming_blocks[0] = after_null_block; - incoming_blocks[1] = after_ok_block; - IrInstSrc *phi = ir_build_phi(irb, parent_scope, node, 2, incoming_blocks, incoming_values, peer_parent); - return ir_lval_wrap(irb, parent_scope, phi, lval, result_loc); -} - -static IrInstSrc *ir_gen_error_union(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node) { - assert(node->type == NodeTypeBinOpExpr); - - AstNode *op1_node = node->data.bin_op_expr.op1; - AstNode *op2_node = node->data.bin_op_expr.op2; - - IrInstSrc *err_set = ir_gen_node(irb, op1_node, parent_scope); - if (err_set == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - - IrInstSrc *payload = ir_gen_node(irb, op2_node, parent_scope); - if (payload == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - - return ir_build_error_union(irb, parent_scope, node, err_set, payload); -} - -static IrInstSrc *ir_gen_bin_op(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { - assert(node->type == NodeTypeBinOpExpr); - - BinOpType bin_op_type = node->data.bin_op_expr.bin_op; - switch (bin_op_type) { - case BinOpTypeInvalid: - zig_unreachable(); - case BinOpTypeAssign: - return ir_lval_wrap(irb, scope, ir_gen_assign(irb, scope, node), lval, result_loc); - case BinOpTypeAssignTimes: - return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpMult), lval, result_loc); - case BinOpTypeAssignTimesWrap: - return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpMultWrap), lval, result_loc); - case BinOpTypeAssignDiv: - return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpDivUnspecified), lval, result_loc); - case BinOpTypeAssignMod: - return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpRemUnspecified), lval, result_loc); - case BinOpTypeAssignPlus: - return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpAdd), lval, result_loc); - case BinOpTypeAssignPlusWrap: - return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpAddWrap), lval, result_loc); - case BinOpTypeAssignMinus: - return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpSub), lval, result_loc); - case BinOpTypeAssignMinusWrap: - return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpSubWrap), lval, result_loc); - case BinOpTypeAssignBitShiftLeft: - return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpBitShiftLeftLossy), lval, result_loc); - case BinOpTypeAssignBitShiftRight: - return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpBitShiftRightLossy), lval, result_loc); - case BinOpTypeAssignBitAnd: - return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpBinAnd), lval, result_loc); - case BinOpTypeAssignBitXor: - return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpBinXor), lval, result_loc); - case BinOpTypeAssignBitOr: - return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpBinOr), lval, result_loc); - case BinOpTypeBoolOr: - return ir_lval_wrap(irb, scope, ir_gen_bool_or(irb, scope, node), lval, result_loc); - case BinOpTypeBoolAnd: - return ir_lval_wrap(irb, scope, ir_gen_bool_and(irb, scope, node), lval, result_loc); - case BinOpTypeCmpEq: - return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpEq), lval, result_loc); - case BinOpTypeCmpNotEq: - return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpNotEq), lval, result_loc); - case BinOpTypeCmpLessThan: - return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpLessThan), lval, result_loc); - case BinOpTypeCmpGreaterThan: - return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpGreaterThan), lval, result_loc); - case BinOpTypeCmpLessOrEq: - return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpLessOrEq), lval, result_loc); - case BinOpTypeCmpGreaterOrEq: - return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpGreaterOrEq), lval, result_loc); - case BinOpTypeBinOr: - return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpBinOr), lval, result_loc); - case BinOpTypeBinXor: - return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpBinXor), lval, result_loc); - case BinOpTypeBinAnd: - return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpBinAnd), lval, result_loc); - case BinOpTypeBitShiftLeft: - return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpBitShiftLeftLossy), lval, result_loc); - case BinOpTypeBitShiftRight: - return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpBitShiftRightLossy), lval, result_loc); - case BinOpTypeAdd: - return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpAdd), lval, result_loc); - case BinOpTypeAddWrap: - return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpAddWrap), lval, result_loc); - case BinOpTypeSub: - return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpSub), lval, result_loc); - case BinOpTypeSubWrap: - return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpSubWrap), lval, result_loc); - case BinOpTypeMult: - return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpMult), lval, result_loc); - case BinOpTypeMultWrap: - return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpMultWrap), lval, result_loc); - case BinOpTypeDiv: - return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpDivUnspecified), lval, result_loc); - case BinOpTypeMod: - return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpRemUnspecified), lval, result_loc); - case BinOpTypeArrayCat: - return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpArrayCat), lval, result_loc); - case BinOpTypeArrayMult: - return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpArrayMult), lval, result_loc); - case BinOpTypeMergeErrorSets: - return ir_lval_wrap(irb, scope, ir_gen_merge_err_sets(irb, scope, node), lval, result_loc); - case BinOpTypeUnwrapOptional: - return ir_gen_orelse(irb, scope, node, lval, result_loc); - case BinOpTypeErrorUnion: - return ir_lval_wrap(irb, scope, ir_gen_error_union(irb, scope, node), lval, result_loc); - } - zig_unreachable(); -} - -static IrInstSrc *ir_gen_int_lit(IrBuilderSrc *irb, Scope *scope, AstNode *node) { - assert(node->type == NodeTypeIntLiteral); - - return ir_build_const_bigint(irb, scope, node, node->data.int_literal.bigint); -} - -static IrInstSrc *ir_gen_float_lit(IrBuilderSrc *irb, Scope *scope, AstNode *node) { - assert(node->type == NodeTypeFloatLiteral); - - if (node->data.float_literal.overflow) { - add_node_error(irb->codegen, node, buf_sprintf("float literal out of range of any type")); - return irb->codegen->invalid_inst_src; - } - - return ir_build_const_bigfloat(irb, scope, node, node->data.float_literal.bigfloat); -} - -static IrInstSrc *ir_gen_char_lit(IrBuilderSrc *irb, Scope *scope, AstNode *node) { - assert(node->type == NodeTypeCharLiteral); - - return ir_build_const_uint(irb, scope, node, node->data.char_literal.value); -} - -static IrInstSrc *ir_gen_null_literal(IrBuilderSrc *irb, Scope *scope, AstNode *node) { - assert(node->type == NodeTypeNullLiteral); - - return ir_build_const_null(irb, scope, node); -} - -static void populate_invalid_variable_in_scope(CodeGen *g, Scope *scope, AstNode *node, Buf *var_name) { - ScopeDecls *scope_decls = nullptr; - while (scope != nullptr) { - if (scope->id == ScopeIdDecls) { - scope_decls = reinterpret_cast(scope); - } - scope = scope->parent; - } - TldVar *tld_var = heap::c_allocator.create(); - init_tld(&tld_var->base, TldIdVar, var_name, VisibModPub, node, &scope_decls->base); - tld_var->base.resolution = TldResolutionInvalid; - tld_var->var = add_variable(g, node, &scope_decls->base, var_name, false, - g->invalid_inst_gen->value, &tld_var->base, g->builtin_types.entry_invalid); - scope_decls->decl_table.put(var_name, &tld_var->base); -} - -static IrInstSrc *ir_gen_symbol(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { - Error err; - assert(node->type == NodeTypeSymbol); - - Buf *variable_name = node->data.symbol_expr.symbol; - - if (buf_eql_str(variable_name, "_")) { - if (lval == LValAssign) { - IrInstSrcConst *const_instruction = ir_build_instruction(irb, scope, node); - const_instruction->value = irb->codegen->pass1_arena->create(); - const_instruction->value->type = get_pointer_to_type(irb->codegen, - irb->codegen->builtin_types.entry_void, false); - const_instruction->value->special = ConstValSpecialStatic; - const_instruction->value->data.x_ptr.special = ConstPtrSpecialDiscard; - return &const_instruction->base; - } else { - add_node_error(irb->codegen, node, buf_sprintf("`_` may only be used to assign things to")); - return irb->codegen->invalid_inst_src; - } - } - - ZigType *primitive_type; - if ((err = get_primitive_type(irb->codegen, variable_name, &primitive_type))) { - if (err == ErrorOverflow) { - add_node_error(irb->codegen, node, - buf_sprintf("primitive integer type '%s' exceeds maximum bit width of 65535", - buf_ptr(variable_name))); - return irb->codegen->invalid_inst_src; - } - assert(err == ErrorPrimitiveTypeNotFound); - } else { - IrInstSrc *value = ir_build_const_type(irb, scope, node, primitive_type); - if (lval == LValPtr || lval == LValAssign) { - return ir_build_ref_src(irb, scope, node, value); - } else { - return ir_expr_wrap(irb, scope, value, result_loc); - } - } - - ScopeFnDef *crossed_fndef_scope; - ZigVar *var = find_variable(irb->codegen, scope, variable_name, &crossed_fndef_scope); - if (var) { - IrInstSrc *var_ptr = ir_build_var_ptr_x(irb, scope, node, var, crossed_fndef_scope); - if (lval == LValPtr || lval == LValAssign) { - return var_ptr; - } else { - return ir_expr_wrap(irb, scope, ir_build_load_ptr(irb, scope, node, var_ptr), result_loc); - } - } - - Tld *tld = find_decl(irb->codegen, scope, variable_name); - if (tld) { - IrInstSrc *decl_ref = ir_build_decl_ref(irb, scope, node, tld, lval); - if (lval == LValPtr || lval == LValAssign) { - return decl_ref; - } else { - return ir_expr_wrap(irb, scope, decl_ref, result_loc); - } - } - - if (get_container_scope(node->owner)->any_imports_failed) { - // skip the error message since we had a failing import in this file - // if an import breaks we don't need redundant undeclared identifier errors - return irb->codegen->invalid_inst_src; - } - - return ir_build_undeclared_identifier(irb, scope, node, variable_name); -} - -static IrInstSrc *ir_gen_array_access(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, - ResultLoc *result_loc) -{ - assert(node->type == NodeTypeArrayAccessExpr); - - AstNode *array_ref_node = node->data.array_access_expr.array_ref_expr; - IrInstSrc *array_ref_instruction = ir_gen_node_extra(irb, array_ref_node, scope, LValPtr, nullptr); - if (array_ref_instruction == irb->codegen->invalid_inst_src) - return array_ref_instruction; - - // Create an usize-typed result location to hold the subscript value, this - // makes it possible for the compiler to infer the subscript expression type - // if needed - IrInstSrc *usize_type_inst = ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_usize); - ResultLocCast *result_loc_cast = ir_build_cast_result_loc(irb, usize_type_inst, no_result_loc()); - - AstNode *subscript_node = node->data.array_access_expr.subscript; - IrInstSrc *subscript_value = ir_gen_node_extra(irb, subscript_node, scope, LValNone, &result_loc_cast->base); - if (subscript_value == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - - IrInstSrc *subscript_instruction = ir_build_implicit_cast(irb, scope, subscript_node, subscript_value, result_loc_cast); - - IrInstSrc *ptr_instruction = ir_build_elem_ptr(irb, scope, node, array_ref_instruction, - subscript_instruction, true, PtrLenSingle, nullptr); - if (lval == LValPtr || lval == LValAssign) - return ptr_instruction; - - IrInstSrc *load_ptr = ir_build_load_ptr(irb, scope, node, ptr_instruction); - return ir_expr_wrap(irb, scope, load_ptr, result_loc); -} - -static IrInstSrc *ir_gen_field_access(IrBuilderSrc *irb, Scope *scope, AstNode *node) { - assert(node->type == NodeTypeFieldAccessExpr); - - AstNode *container_ref_node = node->data.field_access_expr.struct_expr; - Buf *field_name = node->data.field_access_expr.field_name; - - IrInstSrc *container_ref_instruction = ir_gen_node_extra(irb, container_ref_node, scope, LValPtr, nullptr); - if (container_ref_instruction == irb->codegen->invalid_inst_src) - return container_ref_instruction; - - return ir_build_field_ptr(irb, scope, node, container_ref_instruction, field_name, false); -} - -static IrInstSrc *ir_gen_overflow_op(IrBuilderSrc *irb, Scope *scope, AstNode *node, IrOverflowOp op) { - assert(node->type == NodeTypeFnCallExpr); - - AstNode *type_node = node->data.fn_call_expr.params.at(0); - AstNode *op1_node = node->data.fn_call_expr.params.at(1); - AstNode *op2_node = node->data.fn_call_expr.params.at(2); - AstNode *result_ptr_node = node->data.fn_call_expr.params.at(3); - - - IrInstSrc *type_value = ir_gen_node(irb, type_node, scope); - if (type_value == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - - IrInstSrc *op1 = ir_gen_node(irb, op1_node, scope); - if (op1 == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - - IrInstSrc *op2 = ir_gen_node(irb, op2_node, scope); - if (op2 == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - - IrInstSrc *result_ptr = ir_gen_node(irb, result_ptr_node, scope); - if (result_ptr == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - - return ir_build_overflow_op_src(irb, scope, node, op, type_value, op1, op2, result_ptr); -} - -static IrInstSrc *ir_gen_mul_add(IrBuilderSrc *irb, Scope *scope, AstNode *node) { - assert(node->type == NodeTypeFnCallExpr); - - AstNode *type_node = node->data.fn_call_expr.params.at(0); - AstNode *op1_node = node->data.fn_call_expr.params.at(1); - AstNode *op2_node = node->data.fn_call_expr.params.at(2); - AstNode *op3_node = node->data.fn_call_expr.params.at(3); - - IrInstSrc *type_value = ir_gen_node(irb, type_node, scope); - if (type_value == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - - IrInstSrc *op1 = ir_gen_node(irb, op1_node, scope); - if (op1 == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - - IrInstSrc *op2 = ir_gen_node(irb, op2_node, scope); - if (op2 == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - - IrInstSrc *op3 = ir_gen_node(irb, op3_node, scope); - if (op3 == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - - return ir_build_mul_add_src(irb, scope, node, type_value, op1, op2, op3); -} - -static IrInstSrc *ir_gen_this(IrBuilderSrc *irb, Scope *orig_scope, AstNode *node) { - for (Scope *it_scope = orig_scope; it_scope != nullptr; it_scope = it_scope->parent) { - if (it_scope->id == ScopeIdDecls) { - ScopeDecls *decls_scope = (ScopeDecls *)it_scope; - ZigType *container_type = decls_scope->container_type; - if (container_type != nullptr) { - return ir_build_const_type(irb, orig_scope, node, container_type); - } else { - return ir_build_const_import(irb, orig_scope, node, decls_scope->import); - } - } - } - zig_unreachable(); -} - -static IrInstSrc *ir_gen_async_call(IrBuilderSrc *irb, Scope *scope, AstNode *await_node, AstNode *call_node, - LVal lval, ResultLoc *result_loc) -{ - if (call_node->data.fn_call_expr.params.length != 4) { - add_node_error(irb->codegen, call_node, - buf_sprintf("expected 4 arguments, found %" ZIG_PRI_usize, - call_node->data.fn_call_expr.params.length)); - return irb->codegen->invalid_inst_src; - } - - AstNode *bytes_node = call_node->data.fn_call_expr.params.at(0); - IrInstSrc *bytes = ir_gen_node(irb, bytes_node, scope); - if (bytes == irb->codegen->invalid_inst_src) - return bytes; - - AstNode *ret_ptr_node = call_node->data.fn_call_expr.params.at(1); - IrInstSrc *ret_ptr = ir_gen_node(irb, ret_ptr_node, scope); - if (ret_ptr == irb->codegen->invalid_inst_src) - return ret_ptr; - - AstNode *fn_ref_node = call_node->data.fn_call_expr.params.at(2); - IrInstSrc *fn_ref = ir_gen_node(irb, fn_ref_node, scope); - if (fn_ref == irb->codegen->invalid_inst_src) - return fn_ref; - - CallModifier modifier = (await_node == nullptr) ? CallModifierAsync : CallModifierNone; - bool is_async_call_builtin = true; - AstNode *args_node = call_node->data.fn_call_expr.params.at(3); - if (args_node->type == NodeTypeContainerInitExpr) { - if (args_node->data.container_init_expr.kind == ContainerInitKindArray || - args_node->data.container_init_expr.entries.length == 0) - { - size_t arg_count = args_node->data.container_init_expr.entries.length; - IrInstSrc **args = heap::c_allocator.allocate(arg_count); - for (size_t i = 0; i < arg_count; i += 1) { - AstNode *arg_node = args_node->data.container_init_expr.entries.at(i); - IrInstSrc *arg = ir_gen_node(irb, arg_node, scope); - if (arg == irb->codegen->invalid_inst_src) - return arg; - args[i] = arg; - } - - IrInstSrc *call = ir_build_call_src(irb, scope, call_node, nullptr, fn_ref, arg_count, args, - ret_ptr, modifier, is_async_call_builtin, bytes, result_loc); - return ir_lval_wrap(irb, scope, call, lval, result_loc); - } else { - exec_add_error_node(irb->codegen, irb->exec, args_node, - buf_sprintf("TODO: @asyncCall with anon struct literal")); - return irb->codegen->invalid_inst_src; - } - } - IrInstSrc *args = ir_gen_node(irb, args_node, scope); - if (args == irb->codegen->invalid_inst_src) - return args; - - IrInstSrc *call = ir_build_async_call_extra(irb, scope, call_node, modifier, fn_ref, ret_ptr, bytes, args, result_loc); - return ir_lval_wrap(irb, scope, call, lval, result_loc); -} - -static IrInstSrc *ir_gen_fn_call_with_args(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - AstNode *fn_ref_node, CallModifier modifier, IrInstSrc *options, - AstNode **args_ptr, size_t args_len, LVal lval, ResultLoc *result_loc) -{ - IrInstSrc *fn_ref = ir_gen_node(irb, fn_ref_node, scope); - if (fn_ref == irb->codegen->invalid_inst_src) - return fn_ref; - - IrInstSrc *fn_type = ir_build_typeof_1(irb, scope, source_node, fn_ref); - - IrInstSrc **args = heap::c_allocator.allocate(args_len); - for (size_t i = 0; i < args_len; i += 1) { - AstNode *arg_node = args_ptr[i]; - - IrInstSrc *arg_index = ir_build_const_usize(irb, scope, arg_node, i); - IrInstSrc *arg_type = ir_build_arg_type(irb, scope, source_node, fn_type, arg_index, true); - ResultLoc *no_result = no_result_loc(); - ir_build_reset_result(irb, scope, source_node, no_result); - ResultLocCast *result_loc_cast = ir_build_cast_result_loc(irb, arg_type, no_result); - - IrInstSrc *arg = ir_gen_node_extra(irb, arg_node, scope, LValNone, &result_loc_cast->base); - if (arg == irb->codegen->invalid_inst_src) - return arg; - - args[i] = ir_build_implicit_cast(irb, scope, arg_node, arg, result_loc_cast); - } - - IrInstSrc *fn_call; - if (options != nullptr) { - fn_call = ir_build_call_args(irb, scope, source_node, options, fn_ref, args, args_len, result_loc); - } else { - fn_call = ir_build_call_src(irb, scope, source_node, nullptr, fn_ref, args_len, args, nullptr, - modifier, false, nullptr, result_loc); - } - return ir_lval_wrap(irb, scope, fn_call, lval, result_loc); -} - -static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, - ResultLoc *result_loc) -{ - assert(node->type == NodeTypeFnCallExpr); - - AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr; - Buf *name = fn_ref_expr->data.symbol_expr.symbol; - auto entry = irb->codegen->builtin_fn_table.maybe_get(name); - - if (!entry) { - add_node_error(irb->codegen, node, - buf_sprintf("invalid builtin function: '%s'", buf_ptr(name))); - return irb->codegen->invalid_inst_src; - } - - BuiltinFnEntry *builtin_fn = entry->value; - size_t actual_param_count = node->data.fn_call_expr.params.length; - - if (builtin_fn->param_count != SIZE_MAX && builtin_fn->param_count != actual_param_count) { - add_node_error(irb->codegen, node, - buf_sprintf("expected %" ZIG_PRI_usize " argument(s), found %" ZIG_PRI_usize, - builtin_fn->param_count, actual_param_count)); - return irb->codegen->invalid_inst_src; - } - - switch (builtin_fn->id) { - case BuiltinFnIdInvalid: - zig_unreachable(); - case BuiltinFnIdTypeof: - { - Scope *sub_scope = create_typeof_scope(irb->codegen, node, scope); - - size_t arg_count = node->data.fn_call_expr.params.length; - - IrInstSrc *type_of; - - if (arg_count == 0) { - add_node_error(irb->codegen, node, - buf_sprintf("expected at least 1 argument, found 0")); - return irb->codegen->invalid_inst_src; - } else if (arg_count == 1) { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, sub_scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - type_of = ir_build_typeof_1(irb, scope, node, arg0_value); - } else { - IrInstSrc **args = heap::c_allocator.allocate(arg_count); - for (size_t i = 0; i < arg_count; i += 1) { - AstNode *arg_node = node->data.fn_call_expr.params.at(i); - IrInstSrc *arg = ir_gen_node(irb, arg_node, sub_scope); - if (arg == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - args[i] = arg; - } - - type_of = ir_build_typeof_n(irb, scope, node, args, arg_count); - } - return ir_lval_wrap(irb, scope, type_of, lval, result_loc); - } - case BuiltinFnIdSetCold: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - IrInstSrc *set_cold = ir_build_set_cold(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, set_cold, lval, result_loc); - } - case BuiltinFnIdSetRuntimeSafety: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - IrInstSrc *set_safety = ir_build_set_runtime_safety(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, set_safety, lval, result_loc); - } - case BuiltinFnIdSetFloatMode: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - IrInstSrc *set_float_mode = ir_build_set_float_mode(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, set_float_mode, lval, result_loc); - } - case BuiltinFnIdSizeof: - case BuiltinFnIdBitSizeof: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - IrInstSrc *size_of = ir_build_size_of(irb, scope, node, arg0_value, builtin_fn->id == BuiltinFnIdBitSizeof); - return ir_lval_wrap(irb, scope, size_of, lval, result_loc); - } - case BuiltinFnIdImport: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - IrInstSrc *import = ir_build_import(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, import, lval, result_loc); - } - case BuiltinFnIdCImport: - { - IrInstSrc *c_import = ir_build_c_import(irb, scope, node); - return ir_lval_wrap(irb, scope, c_import, lval, result_loc); - } - case BuiltinFnIdCInclude: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - if (!exec_c_import_buf(irb->exec)) { - add_node_error(irb->codegen, node, buf_sprintf("C include valid only inside C import block")); - return irb->codegen->invalid_inst_src; - } - - IrInstSrc *c_include = ir_build_c_include(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, c_include, lval, result_loc); - } - case BuiltinFnIdCDefine: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) - return arg1_value; - - if (!exec_c_import_buf(irb->exec)) { - add_node_error(irb->codegen, node, buf_sprintf("C define valid only inside C import block")); - return irb->codegen->invalid_inst_src; - } - - IrInstSrc *c_define = ir_build_c_define(irb, scope, node, arg0_value, arg1_value); - return ir_lval_wrap(irb, scope, c_define, lval, result_loc); - } - case BuiltinFnIdCUndef: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - if (!exec_c_import_buf(irb->exec)) { - add_node_error(irb->codegen, node, buf_sprintf("C undef valid only inside C import block")); - return irb->codegen->invalid_inst_src; - } - - IrInstSrc *c_undef = ir_build_c_undef(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, c_undef, lval, result_loc); - } - case BuiltinFnIdCompileErr: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - IrInstSrc *compile_err = ir_build_compile_err(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, compile_err, lval, result_loc); - } - case BuiltinFnIdCompileLog: - { - IrInstSrc **args = heap::c_allocator.allocate(actual_param_count); - - for (size_t i = 0; i < actual_param_count; i += 1) { - AstNode *arg_node = node->data.fn_call_expr.params.at(i); - args[i] = ir_gen_node(irb, arg_node, scope); - if (args[i] == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - } - - IrInstSrc *compile_log = ir_build_compile_log(irb, scope, node, actual_param_count, args); - return ir_lval_wrap(irb, scope, compile_log, lval, result_loc); - } - case BuiltinFnIdErrName: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - IrInstSrc *err_name = ir_build_err_name(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, err_name, lval, result_loc); - } - case BuiltinFnIdEmbedFile: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - IrInstSrc *embed_file = ir_build_embed_file(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, embed_file, lval, result_loc); - } - case BuiltinFnIdCmpxchgWeak: - case BuiltinFnIdCmpxchgStrong: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) - return arg1_value; - - AstNode *arg2_node = node->data.fn_call_expr.params.at(2); - IrInstSrc *arg2_value = ir_gen_node(irb, arg2_node, scope); - if (arg2_value == irb->codegen->invalid_inst_src) - return arg2_value; - - AstNode *arg3_node = node->data.fn_call_expr.params.at(3); - IrInstSrc *arg3_value = ir_gen_node(irb, arg3_node, scope); - if (arg3_value == irb->codegen->invalid_inst_src) - return arg3_value; - - AstNode *arg4_node = node->data.fn_call_expr.params.at(4); - IrInstSrc *arg4_value = ir_gen_node(irb, arg4_node, scope); - if (arg4_value == irb->codegen->invalid_inst_src) - return arg4_value; - - AstNode *arg5_node = node->data.fn_call_expr.params.at(5); - IrInstSrc *arg5_value = ir_gen_node(irb, arg5_node, scope); - if (arg5_value == irb->codegen->invalid_inst_src) - return arg5_value; - - IrInstSrc *cmpxchg = ir_build_cmpxchg_src(irb, scope, node, arg0_value, arg1_value, - arg2_value, arg3_value, arg4_value, arg5_value, (builtin_fn->id == BuiltinFnIdCmpxchgWeak), - result_loc); - return ir_lval_wrap(irb, scope, cmpxchg, lval, result_loc); - } - case BuiltinFnIdFence: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - IrInstSrc *fence = ir_build_fence(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, fence, lval, result_loc); - } - case BuiltinFnIdReduce: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) - return arg1_value; - - IrInstSrc *reduce = ir_build_reduce(irb, scope, node, arg0_value, arg1_value); - return ir_lval_wrap(irb, scope, reduce, lval, result_loc); - } - case BuiltinFnIdDivExact: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) - return arg1_value; - - IrInstSrc *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpDivExact, arg0_value, arg1_value, true); - return ir_lval_wrap(irb, scope, bin_op, lval, result_loc); - } - case BuiltinFnIdDivTrunc: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) - return arg1_value; - - IrInstSrc *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpDivTrunc, arg0_value, arg1_value, true); - return ir_lval_wrap(irb, scope, bin_op, lval, result_loc); - } - case BuiltinFnIdDivFloor: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) - return arg1_value; - - IrInstSrc *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpDivFloor, arg0_value, arg1_value, true); - return ir_lval_wrap(irb, scope, bin_op, lval, result_loc); - } - case BuiltinFnIdRem: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) - return arg1_value; - - IrInstSrc *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpRemRem, arg0_value, arg1_value, true); - return ir_lval_wrap(irb, scope, bin_op, lval, result_loc); - } - case BuiltinFnIdMod: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) - return arg1_value; - - IrInstSrc *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpRemMod, arg0_value, arg1_value, true); - return ir_lval_wrap(irb, scope, bin_op, lval, result_loc); - } - case BuiltinFnIdSqrt: - case BuiltinFnIdSin: - case BuiltinFnIdCos: - case BuiltinFnIdExp: - case BuiltinFnIdExp2: - case BuiltinFnIdLog: - case BuiltinFnIdLog2: - case BuiltinFnIdLog10: - case BuiltinFnIdFabs: - case BuiltinFnIdFloor: - case BuiltinFnIdCeil: - case BuiltinFnIdTrunc: - case BuiltinFnIdNearbyInt: - case BuiltinFnIdRound: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - IrInstSrc *inst = ir_build_float_op_src(irb, scope, node, arg0_value, builtin_fn->id); - return ir_lval_wrap(irb, scope, inst, lval, result_loc); - } - case BuiltinFnIdTruncate: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) - return arg1_value; - - IrInstSrc *truncate = ir_build_truncate(irb, scope, node, arg0_value, arg1_value); - return ir_lval_wrap(irb, scope, truncate, lval, result_loc); - } - case BuiltinFnIdIntCast: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) - return arg1_value; - - IrInstSrc *result = ir_build_int_cast(irb, scope, node, arg0_value, arg1_value); - return ir_lval_wrap(irb, scope, result, lval, result_loc); - } - case BuiltinFnIdFloatCast: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) - return arg1_value; - - IrInstSrc *result = ir_build_float_cast(irb, scope, node, arg0_value, arg1_value); - return ir_lval_wrap(irb, scope, result, lval, result_loc); - } - case BuiltinFnIdErrSetCast: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) - return arg1_value; - - IrInstSrc *result = ir_build_err_set_cast(irb, scope, node, arg0_value, arg1_value); - return ir_lval_wrap(irb, scope, result, lval, result_loc); - } - case BuiltinFnIdIntToFloat: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) - return arg1_value; - - IrInstSrc *result = ir_build_int_to_float(irb, scope, node, arg0_value, arg1_value); - return ir_lval_wrap(irb, scope, result, lval, result_loc); - } - case BuiltinFnIdFloatToInt: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) - return arg1_value; - - IrInstSrc *result = ir_build_float_to_int(irb, scope, node, arg0_value, arg1_value); - return ir_lval_wrap(irb, scope, result, lval, result_loc); - } - case BuiltinFnIdErrToInt: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - IrInstSrc *result = ir_build_err_to_int_src(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, result, lval, result_loc); - } - case BuiltinFnIdIntToErr: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - IrInstSrc *result = ir_build_int_to_err_src(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, result, lval, result_loc); - } - case BuiltinFnIdBoolToInt: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - IrInstSrc *result = ir_build_bool_to_int(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, result, lval, result_loc); - } - case BuiltinFnIdVectorType: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) - return arg1_value; - - IrInstSrc *vector_type = ir_build_vector_type(irb, scope, node, arg0_value, arg1_value); - return ir_lval_wrap(irb, scope, vector_type, lval, result_loc); - } - case BuiltinFnIdShuffle: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) - return arg1_value; - - AstNode *arg2_node = node->data.fn_call_expr.params.at(2); - IrInstSrc *arg2_value = ir_gen_node(irb, arg2_node, scope); - if (arg2_value == irb->codegen->invalid_inst_src) - return arg2_value; - - AstNode *arg3_node = node->data.fn_call_expr.params.at(3); - IrInstSrc *arg3_value = ir_gen_node(irb, arg3_node, scope); - if (arg3_value == irb->codegen->invalid_inst_src) - return arg3_value; - - IrInstSrc *shuffle_vector = ir_build_shuffle_vector(irb, scope, node, - arg0_value, arg1_value, arg2_value, arg3_value); - return ir_lval_wrap(irb, scope, shuffle_vector, lval, result_loc); - } - case BuiltinFnIdSplat: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) - return arg1_value; - - IrInstSrc *splat = ir_build_splat_src(irb, scope, node, - arg0_value, arg1_value); - return ir_lval_wrap(irb, scope, splat, lval, result_loc); - } - case BuiltinFnIdMemcpy: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) - return arg1_value; - - AstNode *arg2_node = node->data.fn_call_expr.params.at(2); - IrInstSrc *arg2_value = ir_gen_node(irb, arg2_node, scope); - if (arg2_value == irb->codegen->invalid_inst_src) - return arg2_value; - - IrInstSrc *ir_memcpy = ir_build_memcpy_src(irb, scope, node, arg0_value, arg1_value, arg2_value); - return ir_lval_wrap(irb, scope, ir_memcpy, lval, result_loc); - } - case BuiltinFnIdMemset: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) - return arg1_value; - - AstNode *arg2_node = node->data.fn_call_expr.params.at(2); - IrInstSrc *arg2_value = ir_gen_node(irb, arg2_node, scope); - if (arg2_value == irb->codegen->invalid_inst_src) - return arg2_value; - - IrInstSrc *ir_memset = ir_build_memset_src(irb, scope, node, arg0_value, arg1_value, arg2_value); - return ir_lval_wrap(irb, scope, ir_memset, lval, result_loc); - } - case BuiltinFnIdWasmMemorySize: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - IrInstSrc *ir_wasm_memory_size = ir_build_wasm_memory_size_src(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, ir_wasm_memory_size, lval, result_loc); - } - case BuiltinFnIdWasmMemoryGrow: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) - return arg1_value; - - IrInstSrc *ir_wasm_memory_grow = ir_build_wasm_memory_grow_src(irb, scope, node, arg0_value, arg1_value); - return ir_lval_wrap(irb, scope, ir_wasm_memory_grow, lval, result_loc); - } - case BuiltinFnIdField: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node_extra(irb, arg0_node, scope, LValPtr, nullptr); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) - return arg1_value; - - IrInstSrc *ptr_instruction = ir_build_field_ptr_instruction(irb, scope, node, - arg0_value, arg1_value, false); - - if (lval == LValPtr || lval == LValAssign) - return ptr_instruction; - - IrInstSrc *load_ptr = ir_build_load_ptr(irb, scope, node, ptr_instruction); - return ir_expr_wrap(irb, scope, load_ptr, result_loc); - } - case BuiltinFnIdHasField: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) - return arg1_value; - - IrInstSrc *type_info = ir_build_has_field(irb, scope, node, arg0_value, arg1_value); - return ir_lval_wrap(irb, scope, type_info, lval, result_loc); - } - case BuiltinFnIdTypeInfo: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - IrInstSrc *type_info = ir_build_type_info(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, type_info, lval, result_loc); - } - case BuiltinFnIdType: - { - AstNode *arg_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg = ir_gen_node(irb, arg_node, scope); - if (arg == irb->codegen->invalid_inst_src) - return arg; - - IrInstSrc *type = ir_build_type(irb, scope, node, arg); - return ir_lval_wrap(irb, scope, type, lval, result_loc); - } - case BuiltinFnIdBreakpoint: - return ir_lval_wrap(irb, scope, ir_build_breakpoint(irb, scope, node), lval, result_loc); - case BuiltinFnIdReturnAddress: - return ir_lval_wrap(irb, scope, ir_build_return_address_src(irb, scope, node), lval, result_loc); - case BuiltinFnIdFrameAddress: - return ir_lval_wrap(irb, scope, ir_build_frame_address_src(irb, scope, node), lval, result_loc); - case BuiltinFnIdFrameHandle: - if (!irb->exec->fn_entry) { - add_node_error(irb->codegen, node, buf_sprintf("@frame() called outside of function definition")); - return irb->codegen->invalid_inst_src; - } - return ir_lval_wrap(irb, scope, ir_build_handle_src(irb, scope, node), lval, result_loc); - case BuiltinFnIdFrameType: { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - IrInstSrc *frame_type = ir_build_frame_type(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, frame_type, lval, result_loc); - } - case BuiltinFnIdFrameSize: { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - IrInstSrc *frame_size = ir_build_frame_size_src(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, frame_size, lval, result_loc); - } - case BuiltinFnIdAlignOf: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - IrInstSrc *align_of = ir_build_align_of(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, align_of, lval, result_loc); - } - case BuiltinFnIdAddWithOverflow: - return ir_lval_wrap(irb, scope, ir_gen_overflow_op(irb, scope, node, IrOverflowOpAdd), lval, result_loc); - case BuiltinFnIdSubWithOverflow: - return ir_lval_wrap(irb, scope, ir_gen_overflow_op(irb, scope, node, IrOverflowOpSub), lval, result_loc); - case BuiltinFnIdMulWithOverflow: - return ir_lval_wrap(irb, scope, ir_gen_overflow_op(irb, scope, node, IrOverflowOpMul), lval, result_loc); - case BuiltinFnIdShlWithOverflow: - return ir_lval_wrap(irb, scope, ir_gen_overflow_op(irb, scope, node, IrOverflowOpShl), lval, result_loc); - case BuiltinFnIdMulAdd: - return ir_lval_wrap(irb, scope, ir_gen_mul_add(irb, scope, node), lval, result_loc); - case BuiltinFnIdTypeName: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - IrInstSrc *type_name = ir_build_type_name(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, type_name, lval, result_loc); - } - case BuiltinFnIdPanic: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - IrInstSrc *panic = ir_build_panic_src(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, panic, lval, result_loc); - } - case BuiltinFnIdPtrCast: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) - return arg1_value; - - IrInstSrc *ptr_cast = ir_build_ptr_cast_src(irb, scope, node, arg0_value, arg1_value, true); - return ir_lval_wrap(irb, scope, ptr_cast, lval, result_loc); - } - case BuiltinFnIdBitCast: - { - AstNode *dest_type_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *dest_type = ir_gen_node(irb, dest_type_node, scope); - if (dest_type == irb->codegen->invalid_inst_src) - return dest_type; - - ResultLocBitCast *result_loc_bit_cast = heap::c_allocator.create(); - result_loc_bit_cast->base.id = ResultLocIdBitCast; - result_loc_bit_cast->base.source_instruction = dest_type; - result_loc_bit_cast->base.allow_write_through_const = result_loc->allow_write_through_const; - ir_ref_instruction(dest_type, irb->current_basic_block); - result_loc_bit_cast->parent = result_loc; - - ir_build_reset_result(irb, scope, node, &result_loc_bit_cast->base); - - AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node_extra(irb, arg1_node, scope, LValNone, - &result_loc_bit_cast->base); - if (arg1_value == irb->codegen->invalid_inst_src) - return arg1_value; - - IrInstSrc *bitcast = ir_build_bit_cast_src(irb, scope, arg1_node, arg1_value, result_loc_bit_cast); - return ir_lval_wrap(irb, scope, bitcast, lval, result_loc); - } - case BuiltinFnIdAs: - { - AstNode *dest_type_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *dest_type = ir_gen_node(irb, dest_type_node, scope); - if (dest_type == irb->codegen->invalid_inst_src) - return dest_type; - - ResultLocCast *result_loc_cast = ir_build_cast_result_loc(irb, dest_type, result_loc); - - AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node_extra(irb, arg1_node, scope, LValNone, - &result_loc_cast->base); - if (arg1_value == irb->codegen->invalid_inst_src) - return arg1_value; - - IrInstSrc *result = ir_build_implicit_cast(irb, scope, node, arg1_value, result_loc_cast); - return ir_lval_wrap(irb, scope, result, lval, result_loc); - } - case BuiltinFnIdIntToPtr: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) - return arg1_value; - - IrInstSrc *int_to_ptr = ir_build_int_to_ptr_src(irb, scope, node, arg0_value, arg1_value); - return ir_lval_wrap(irb, scope, int_to_ptr, lval, result_loc); - } - case BuiltinFnIdPtrToInt: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - IrInstSrc *ptr_to_int = ir_build_ptr_to_int_src(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, ptr_to_int, lval, result_loc); - } - case BuiltinFnIdTagName: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - IrInstSrc *tag_name = ir_build_tag_name_src(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, tag_name, lval, result_loc); - } - case BuiltinFnIdFieldParentPtr: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) - return arg1_value; - - AstNode *arg2_node = node->data.fn_call_expr.params.at(2); - IrInstSrc *arg2_value = ir_gen_node(irb, arg2_node, scope); - if (arg2_value == irb->codegen->invalid_inst_src) - return arg2_value; - - IrInstSrc *field_parent_ptr = ir_build_field_parent_ptr_src(irb, scope, node, - arg0_value, arg1_value, arg2_value); - return ir_lval_wrap(irb, scope, field_parent_ptr, lval, result_loc); - } - case BuiltinFnIdByteOffsetOf: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) - return arg1_value; - - IrInstSrc *offset_of = ir_build_byte_offset_of(irb, scope, node, arg0_value, arg1_value); - return ir_lval_wrap(irb, scope, offset_of, lval, result_loc); - } - case BuiltinFnIdBitOffsetOf: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) - return arg1_value; - - IrInstSrc *offset_of = ir_build_bit_offset_of(irb, scope, node, arg0_value, arg1_value); - return ir_lval_wrap(irb, scope, offset_of, lval, result_loc); - } - case BuiltinFnIdCall: { - // Cast the options parameter to the options type - ZigType *options_type = get_builtin_type(irb->codegen, "CallOptions"); - IrInstSrc *options_type_inst = ir_build_const_type(irb, scope, node, options_type); - ResultLocCast *result_loc_cast = ir_build_cast_result_loc(irb, options_type_inst, no_result_loc()); - - AstNode *options_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *options_inner = ir_gen_node_extra(irb, options_node, scope, - LValNone, &result_loc_cast->base); - if (options_inner == irb->codegen->invalid_inst_src) - return options_inner; - IrInstSrc *options = ir_build_implicit_cast(irb, scope, options_node, options_inner, result_loc_cast); - - AstNode *fn_ref_node = node->data.fn_call_expr.params.at(1); - AstNode *args_node = node->data.fn_call_expr.params.at(2); - if (args_node->type == NodeTypeContainerInitExpr) { - if (args_node->data.container_init_expr.kind == ContainerInitKindArray || - args_node->data.container_init_expr.entries.length == 0) - { - return ir_gen_fn_call_with_args(irb, scope, node, - fn_ref_node, CallModifierNone, options, - args_node->data.container_init_expr.entries.items, - args_node->data.container_init_expr.entries.length, - lval, result_loc); - } else { - exec_add_error_node(irb->codegen, irb->exec, args_node, - buf_sprintf("TODO: @call with anon struct literal")); - return irb->codegen->invalid_inst_src; - } - } else { - IrInstSrc *fn_ref = ir_gen_node(irb, fn_ref_node, scope); - if (fn_ref == irb->codegen->invalid_inst_src) - return fn_ref; - - IrInstSrc *args = ir_gen_node(irb, args_node, scope); - if (args == irb->codegen->invalid_inst_src) - return args; - - IrInstSrc *call = ir_build_call_extra(irb, scope, node, options, fn_ref, args, result_loc); - return ir_lval_wrap(irb, scope, call, lval, result_loc); - } - } - case BuiltinFnIdAsyncCall: - return ir_gen_async_call(irb, scope, nullptr, node, lval, result_loc); - case BuiltinFnIdShlExact: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) - return arg1_value; - - IrInstSrc *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpBitShiftLeftExact, arg0_value, arg1_value, true); - return ir_lval_wrap(irb, scope, bin_op, lval, result_loc); - } - case BuiltinFnIdShrExact: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) - return arg1_value; - - IrInstSrc *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpBitShiftRightExact, arg0_value, arg1_value, true); - return ir_lval_wrap(irb, scope, bin_op, lval, result_loc); - } - case BuiltinFnIdSetEvalBranchQuota: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - IrInstSrc *set_eval_branch_quota = ir_build_set_eval_branch_quota(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, set_eval_branch_quota, lval, result_loc); - } - case BuiltinFnIdAlignCast: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) - return arg1_value; - - IrInstSrc *align_cast = ir_build_align_cast_src(irb, scope, node, arg0_value, arg1_value); - return ir_lval_wrap(irb, scope, align_cast, lval, result_loc); - } - case BuiltinFnIdThis: - { - IrInstSrc *this_inst = ir_gen_this(irb, scope, node); - return ir_lval_wrap(irb, scope, this_inst, lval, result_loc); - } - case BuiltinFnIdSetAlignStack: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - IrInstSrc *set_align_stack = ir_build_set_align_stack(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, set_align_stack, lval, result_loc); - } - case BuiltinFnIdExport: - { - // Cast the options parameter to the options type - ZigType *options_type = get_builtin_type(irb->codegen, "ExportOptions"); - IrInstSrc *options_type_inst = ir_build_const_type(irb, scope, node, options_type); - ResultLocCast *result_loc_cast = ir_build_cast_result_loc(irb, options_type_inst, no_result_loc()); - - AstNode *target_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *target_value = ir_gen_node(irb, target_node, scope); - if (target_value == irb->codegen->invalid_inst_src) - return target_value; - - AstNode *options_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *options_value = ir_gen_node_extra(irb, options_node, - scope, LValNone, &result_loc_cast->base); - if (options_value == irb->codegen->invalid_inst_src) - return options_value; - - IrInstSrc *casted_options_value = ir_build_implicit_cast( - irb, scope, options_node, options_value, result_loc_cast); - - IrInstSrc *ir_export = ir_build_export(irb, scope, node, target_value, casted_options_value); - return ir_lval_wrap(irb, scope, ir_export, lval, result_loc); - } - case BuiltinFnIdExtern: - { - // Cast the options parameter to the options type - ZigType *options_type = get_builtin_type(irb->codegen, "ExternOptions"); - IrInstSrc *options_type_inst = ir_build_const_type(irb, scope, node, options_type); - ResultLocCast *result_loc_cast = ir_build_cast_result_loc(irb, options_type_inst, no_result_loc()); - - AstNode *type_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *type_value = ir_gen_node(irb, type_node, scope); - if (type_value == irb->codegen->invalid_inst_src) - return type_value; - - AstNode *options_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *options_value = ir_gen_node_extra(irb, options_node, - scope, LValNone, &result_loc_cast->base); - if (options_value == irb->codegen->invalid_inst_src) - return options_value; - - IrInstSrc *casted_options_value = ir_build_implicit_cast( - irb, scope, options_node, options_value, result_loc_cast); - - IrInstSrc *ir_extern = ir_build_extern(irb, scope, node, type_value, casted_options_value); - return ir_lval_wrap(irb, scope, ir_extern, lval, result_loc); - } - case BuiltinFnIdErrorReturnTrace: - { - IrInstSrc *error_return_trace = ir_build_error_return_trace_src(irb, scope, node, - IrInstErrorReturnTraceNull); - return ir_lval_wrap(irb, scope, error_return_trace, lval, result_loc); - } - case BuiltinFnIdAtomicRmw: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) - return arg1_value; - - AstNode *arg2_node = node->data.fn_call_expr.params.at(2); - IrInstSrc *arg2_value = ir_gen_node(irb, arg2_node, scope); - if (arg2_value == irb->codegen->invalid_inst_src) - return arg2_value; - - AstNode *arg3_node = node->data.fn_call_expr.params.at(3); - IrInstSrc *arg3_value = ir_gen_node(irb, arg3_node, scope); - if (arg3_value == irb->codegen->invalid_inst_src) - return arg3_value; - - AstNode *arg4_node = node->data.fn_call_expr.params.at(4); - IrInstSrc *arg4_value = ir_gen_node(irb, arg4_node, scope); - if (arg4_value == irb->codegen->invalid_inst_src) - return arg4_value; - - IrInstSrc *inst = ir_build_atomic_rmw_src(irb, scope, node, - arg0_value, arg1_value, arg2_value, arg3_value, arg4_value); - return ir_lval_wrap(irb, scope, inst, lval, result_loc); - } - case BuiltinFnIdAtomicLoad: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) - return arg1_value; - - AstNode *arg2_node = node->data.fn_call_expr.params.at(2); - IrInstSrc *arg2_value = ir_gen_node(irb, arg2_node, scope); - if (arg2_value == irb->codegen->invalid_inst_src) - return arg2_value; - - IrInstSrc *inst = ir_build_atomic_load_src(irb, scope, node, arg0_value, arg1_value, arg2_value); - return ir_lval_wrap(irb, scope, inst, lval, result_loc); - } - case BuiltinFnIdAtomicStore: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) - return arg1_value; - - AstNode *arg2_node = node->data.fn_call_expr.params.at(2); - IrInstSrc *arg2_value = ir_gen_node(irb, arg2_node, scope); - if (arg2_value == irb->codegen->invalid_inst_src) - return arg2_value; - - AstNode *arg3_node = node->data.fn_call_expr.params.at(3); - IrInstSrc *arg3_value = ir_gen_node(irb, arg3_node, scope); - if (arg3_value == irb->codegen->invalid_inst_src) - return arg3_value; - - IrInstSrc *inst = ir_build_atomic_store_src(irb, scope, node, arg0_value, arg1_value, - arg2_value, arg3_value); - return ir_lval_wrap(irb, scope, inst, lval, result_loc); - } - case BuiltinFnIdIntToEnum: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) - return arg1_value; - - IrInstSrc *result = ir_build_int_to_enum_src(irb, scope, node, arg0_value, arg1_value); - return ir_lval_wrap(irb, scope, result, lval, result_loc); - } - case BuiltinFnIdEnumToInt: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - IrInstSrc *result = ir_build_enum_to_int(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, result, lval, result_loc); - } - case BuiltinFnIdCtz: - case BuiltinFnIdPopCount: - case BuiltinFnIdClz: - case BuiltinFnIdBswap: - case BuiltinFnIdBitReverse: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) - return arg1_value; - - IrInstSrc *result; - switch (builtin_fn->id) { - case BuiltinFnIdCtz: - result = ir_build_ctz(irb, scope, node, arg0_value, arg1_value); - break; - case BuiltinFnIdPopCount: - result = ir_build_pop_count(irb, scope, node, arg0_value, arg1_value); - break; - case BuiltinFnIdClz: - result = ir_build_clz(irb, scope, node, arg0_value, arg1_value); - break; - case BuiltinFnIdBswap: - result = ir_build_bswap(irb, scope, node, arg0_value, arg1_value); - break; - case BuiltinFnIdBitReverse: - result = ir_build_bit_reverse(irb, scope, node, arg0_value, arg1_value); - break; - default: - zig_unreachable(); - } - return ir_lval_wrap(irb, scope, result, lval, result_loc); - } - case BuiltinFnIdHasDecl: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) - return arg1_value; - - IrInstSrc *has_decl = ir_build_has_decl(irb, scope, node, arg0_value, arg1_value); - return ir_lval_wrap(irb, scope, has_decl, lval, result_loc); - } - case BuiltinFnIdUnionInit: - { - AstNode *union_type_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *union_type_inst = ir_gen_node(irb, union_type_node, scope); - if (union_type_inst == irb->codegen->invalid_inst_src) - return union_type_inst; - - AstNode *name_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *name_inst = ir_gen_node(irb, name_node, scope); - if (name_inst == irb->codegen->invalid_inst_src) - return name_inst; - - AstNode *init_node = node->data.fn_call_expr.params.at(2); - - return ir_gen_union_init_expr(irb, scope, node, union_type_inst, name_inst, init_node, - lval, result_loc); - } - case BuiltinFnIdSrc: - { - IrInstSrc *src_inst = ir_build_src(irb, scope, node); - return ir_lval_wrap(irb, scope, src_inst, lval, result_loc); - } - } - zig_unreachable(); -} - -static ScopeNoSuspend *get_scope_nosuspend(Scope *scope) { - while (scope) { - if (scope->id == ScopeIdNoSuspend) - return (ScopeNoSuspend *)scope; - if (scope->id == ScopeIdFnDef) - return nullptr; - - scope = scope->parent; - } - return nullptr; -} - -static IrInstSrc *ir_gen_fn_call(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, - ResultLoc *result_loc) -{ - assert(node->type == NodeTypeFnCallExpr); - - if (node->data.fn_call_expr.modifier == CallModifierBuiltin) - return ir_gen_builtin_fn_call(irb, scope, node, lval, result_loc); - - bool is_nosuspend = get_scope_nosuspend(scope) != nullptr; - CallModifier modifier = node->data.fn_call_expr.modifier; - if (is_nosuspend && modifier != CallModifierAsync) { - modifier = CallModifierNoSuspend; - } - - AstNode *fn_ref_node = node->data.fn_call_expr.fn_ref_expr; - return ir_gen_fn_call_with_args(irb, scope, node, fn_ref_node, modifier, - nullptr, node->data.fn_call_expr.params.items, node->data.fn_call_expr.params.length, lval, result_loc); -} - -static IrInstSrc *ir_gen_if_bool_expr(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, - ResultLoc *result_loc) -{ - assert(node->type == NodeTypeIfBoolExpr); - - IrInstSrc *condition = ir_gen_node(irb, node->data.if_bool_expr.condition, scope); - if (condition == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - - IrInstSrc *is_comptime; - if (ir_should_inline(irb->exec, scope)) { - is_comptime = ir_build_const_bool(irb, scope, node, true); - } else { - is_comptime = ir_build_test_comptime(irb, scope, node, condition); - } - - AstNode *then_node = node->data.if_bool_expr.then_block; - AstNode *else_node = node->data.if_bool_expr.else_node; - - IrBasicBlockSrc *then_block = ir_create_basic_block(irb, scope, "Then"); - IrBasicBlockSrc *else_block = ir_create_basic_block(irb, scope, "Else"); - IrBasicBlockSrc *endif_block = ir_create_basic_block(irb, scope, "EndIf"); - - IrInstSrc *cond_br_inst = ir_build_cond_br(irb, scope, node, condition, - then_block, else_block, is_comptime); - ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, else_block, endif_block, - result_loc, is_comptime); - - ir_set_cursor_at_end_and_append_block(irb, then_block); - - Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime); - IrInstSrc *then_expr_result = ir_gen_node_extra(irb, then_node, subexpr_scope, lval, - &peer_parent->peers.at(0)->base); - if (then_expr_result == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - IrBasicBlockSrc *after_then_block = irb->current_basic_block; - if (!instr_is_unreachable(then_expr_result)) - ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime)); - - ir_set_cursor_at_end_and_append_block(irb, else_block); - IrInstSrc *else_expr_result; - if (else_node) { - else_expr_result = ir_gen_node_extra(irb, else_node, subexpr_scope, lval, &peer_parent->peers.at(1)->base); - if (else_expr_result == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - } else { - else_expr_result = ir_build_const_void(irb, scope, node); - ir_build_end_expr(irb, scope, node, else_expr_result, &peer_parent->peers.at(1)->base); - } - IrBasicBlockSrc *after_else_block = irb->current_basic_block; - if (!instr_is_unreachable(else_expr_result)) - ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime)); - - ir_set_cursor_at_end_and_append_block(irb, endif_block); - IrInstSrc **incoming_values = heap::c_allocator.allocate(2); - incoming_values[0] = then_expr_result; - incoming_values[1] = else_expr_result; - IrBasicBlockSrc **incoming_blocks = heap::c_allocator.allocate(2); - incoming_blocks[0] = after_then_block; - incoming_blocks[1] = after_else_block; - - IrInstSrc *phi = ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, peer_parent); - return ir_expr_wrap(irb, scope, phi, result_loc); -} - -static IrInstSrc *ir_gen_prefix_op_id_lval(IrBuilderSrc *irb, Scope *scope, AstNode *node, IrUnOp op_id, LVal lval) { - assert(node->type == NodeTypePrefixOpExpr); - AstNode *expr_node = node->data.prefix_op_expr.primary_expr; - - IrInstSrc *value = ir_gen_node_extra(irb, expr_node, scope, lval, nullptr); - if (value == irb->codegen->invalid_inst_src) - return value; - - return ir_build_un_op(irb, scope, node, op_id, value); -} - -static IrInstSrc *ir_gen_prefix_op_id(IrBuilderSrc *irb, Scope *scope, AstNode *node, IrUnOp op_id) { - return ir_gen_prefix_op_id_lval(irb, scope, node, op_id, LValNone); -} - -static IrInstSrc *ir_expr_wrap(IrBuilderSrc *irb, Scope *scope, IrInstSrc *inst, ResultLoc *result_loc) { - if (inst == irb->codegen->invalid_inst_src) return inst; - ir_build_end_expr(irb, scope, inst->base.source_node, inst, result_loc); - return inst; -} - -static IrInstSrc *ir_lval_wrap(IrBuilderSrc *irb, Scope *scope, IrInstSrc *value, LVal lval, - ResultLoc *result_loc) -{ - // This logic must be kept in sync with - // [STMT_EXPR_TEST_THING] <--- (search this token) - if (value == irb->codegen->invalid_inst_src || - instr_is_unreachable(value) || - value->base.source_node->type == NodeTypeDefer || - value->id == IrInstSrcIdDeclVar) - { - return value; - } - - assert(lval != LValAssign); - if (lval == LValPtr) { - // We needed a pointer to a value, but we got a value. So we create - // an instruction which just makes a pointer of it. - return ir_build_ref_src(irb, scope, value->base.source_node, value); - } else if (result_loc != nullptr) { - return ir_expr_wrap(irb, scope, value, result_loc); - } else { - return value; - } - -} - -static PtrLen star_token_to_ptr_len(TokenId token_id) { - switch (token_id) { - case TokenIdStar: - case TokenIdStarStar: - return PtrLenSingle; - case TokenIdLBracket: - return PtrLenUnknown; - case TokenIdSymbol: - return PtrLenC; - default: - zig_unreachable(); - } -} - -static IrInstSrc *ir_gen_pointer_type(IrBuilderSrc *irb, Scope *scope, AstNode *node) { - assert(node->type == NodeTypePointerType); - - PtrLen ptr_len = star_token_to_ptr_len(node->data.pointer_type.star_token->id); - - bool is_const = node->data.pointer_type.is_const; - bool is_volatile = node->data.pointer_type.is_volatile; - bool is_allow_zero = node->data.pointer_type.allow_zero_token != nullptr; - AstNode *sentinel_expr = node->data.pointer_type.sentinel; - AstNode *expr_node = node->data.pointer_type.op_expr; - AstNode *align_expr = node->data.pointer_type.align_expr; - - IrInstSrc *sentinel; - if (sentinel_expr != nullptr) { - sentinel = ir_gen_node(irb, sentinel_expr, scope); - if (sentinel == irb->codegen->invalid_inst_src) - return sentinel; - } else { - sentinel = nullptr; - } - - IrInstSrc *align_value; - if (align_expr != nullptr) { - align_value = ir_gen_node(irb, align_expr, scope); - if (align_value == irb->codegen->invalid_inst_src) - return align_value; - } else { - align_value = nullptr; - } - - IrInstSrc *child_type = ir_gen_node(irb, expr_node, scope); - if (child_type == irb->codegen->invalid_inst_src) - return child_type; - - uint32_t bit_offset_start = 0; - if (node->data.pointer_type.bit_offset_start != nullptr) { - if (!bigint_fits_in_bits(node->data.pointer_type.bit_offset_start, 32, false)) { - Buf *val_buf = buf_alloc(); - bigint_append_buf(val_buf, node->data.pointer_type.bit_offset_start, 10); - exec_add_error_node(irb->codegen, irb->exec, node, - buf_sprintf("value %s too large for u32 bit offset", buf_ptr(val_buf))); - return irb->codegen->invalid_inst_src; - } - bit_offset_start = bigint_as_u32(node->data.pointer_type.bit_offset_start); - } - - uint32_t host_int_bytes = 0; - if (node->data.pointer_type.host_int_bytes != nullptr) { - if (!bigint_fits_in_bits(node->data.pointer_type.host_int_bytes, 32, false)) { - Buf *val_buf = buf_alloc(); - bigint_append_buf(val_buf, node->data.pointer_type.host_int_bytes, 10); - exec_add_error_node(irb->codegen, irb->exec, node, - buf_sprintf("value %s too large for u32 byte count", buf_ptr(val_buf))); - return irb->codegen->invalid_inst_src; - } - host_int_bytes = bigint_as_u32(node->data.pointer_type.host_int_bytes); - } - - if (host_int_bytes != 0 && bit_offset_start >= host_int_bytes * 8) { - exec_add_error_node(irb->codegen, irb->exec, node, - buf_sprintf("bit offset starts after end of host integer")); - return irb->codegen->invalid_inst_src; - } - - return ir_build_ptr_type(irb, scope, node, child_type, is_const, is_volatile, - ptr_len, sentinel, align_value, bit_offset_start, host_int_bytes, is_allow_zero); -} - -static IrInstSrc *ir_gen_catch_unreachable(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - AstNode *expr_node, LVal lval, ResultLoc *result_loc) -{ - IrInstSrc *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr); - if (err_union_ptr == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - - IrInstSrc *payload_ptr = ir_build_unwrap_err_payload_src(irb, scope, source_node, err_union_ptr, true, false); - if (payload_ptr == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - - if (lval == LValPtr) - return payload_ptr; - - IrInstSrc *load_ptr = ir_build_load_ptr(irb, scope, source_node, payload_ptr); - return ir_expr_wrap(irb, scope, load_ptr, result_loc); -} - -static IrInstSrc *ir_gen_bool_not(IrBuilderSrc *irb, Scope *scope, AstNode *node) { - assert(node->type == NodeTypePrefixOpExpr); - AstNode *expr_node = node->data.prefix_op_expr.primary_expr; - - IrInstSrc *value = ir_gen_node(irb, expr_node, scope); - if (value == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - - return ir_build_bool_not(irb, scope, node, value); -} - -static IrInstSrc *ir_gen_prefix_op_expr(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, - ResultLoc *result_loc) -{ - assert(node->type == NodeTypePrefixOpExpr); - - PrefixOp prefix_op = node->data.prefix_op_expr.prefix_op; - - switch (prefix_op) { - case PrefixOpInvalid: - zig_unreachable(); - case PrefixOpBoolNot: - return ir_lval_wrap(irb, scope, ir_gen_bool_not(irb, scope, node), lval, result_loc); - case PrefixOpBinNot: - return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpBinNot), lval, result_loc); - case PrefixOpNegation: - return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegation), lval, result_loc); - case PrefixOpNegationWrap: - return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegationWrap), lval, result_loc); - case PrefixOpOptional: - return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpOptional), lval, result_loc); - case PrefixOpAddrOf: { - AstNode *expr_node = node->data.prefix_op_expr.primary_expr; - return ir_lval_wrap(irb, scope, ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr), lval, result_loc); - } - } - zig_unreachable(); -} - -static IrInstSrc *ir_gen_union_init_expr(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *union_type, IrInstSrc *field_name, AstNode *expr_node, - LVal lval, ResultLoc *parent_result_loc) -{ - IrInstSrc *container_ptr = ir_build_resolve_result(irb, scope, source_node, parent_result_loc, union_type); - IrInstSrc *field_ptr = ir_build_field_ptr_instruction(irb, scope, source_node, container_ptr, - field_name, true); - - ResultLocInstruction *result_loc_inst = heap::c_allocator.create(); - result_loc_inst->base.id = ResultLocIdInstruction; - result_loc_inst->base.source_instruction = field_ptr; - ir_ref_instruction(field_ptr, irb->current_basic_block); - ir_build_reset_result(irb, scope, expr_node, &result_loc_inst->base); - - IrInstSrc *expr_value = ir_gen_node_extra(irb, expr_node, scope, LValNone, - &result_loc_inst->base); - if (expr_value == irb->codegen->invalid_inst_src) - return expr_value; - - IrInstSrc *init_union = ir_build_union_init_named_field(irb, scope, source_node, union_type, - field_name, field_ptr, container_ptr); - - return ir_lval_wrap(irb, scope, init_union, lval, parent_result_loc); -} - -static IrInstSrc *ir_gen_container_init_expr(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, - ResultLoc *parent_result_loc) -{ - assert(node->type == NodeTypeContainerInitExpr); - - AstNodeContainerInitExpr *container_init_expr = &node->data.container_init_expr; - ContainerInitKind kind = container_init_expr->kind; - - ResultLocCast *result_loc_cast = nullptr; - ResultLoc *child_result_loc; - AstNode *init_array_type_source_node; - if (container_init_expr->type != nullptr) { - IrInstSrc *container_type; - if (container_init_expr->type->type == NodeTypeInferredArrayType) { - if (kind == ContainerInitKindStruct) { - add_node_error(irb->codegen, container_init_expr->type, - buf_sprintf("initializing array with struct syntax")); - return irb->codegen->invalid_inst_src; - } - IrInstSrc *sentinel; - if (container_init_expr->type->data.inferred_array_type.sentinel != nullptr) { - sentinel = ir_gen_node(irb, container_init_expr->type->data.inferred_array_type.sentinel, scope); - if (sentinel == irb->codegen->invalid_inst_src) - return sentinel; - } else { - sentinel = nullptr; - } - - IrInstSrc *elem_type = ir_gen_node(irb, - container_init_expr->type->data.inferred_array_type.child_type, scope); - if (elem_type == irb->codegen->invalid_inst_src) - return elem_type; - size_t item_count = container_init_expr->entries.length; - IrInstSrc *item_count_inst = ir_build_const_usize(irb, scope, node, item_count); - container_type = ir_build_array_type(irb, scope, node, item_count_inst, sentinel, elem_type); - } else { - container_type = ir_gen_node(irb, container_init_expr->type, scope); - if (container_type == irb->codegen->invalid_inst_src) - return container_type; - } - - result_loc_cast = ir_build_cast_result_loc(irb, container_type, parent_result_loc); - child_result_loc = &result_loc_cast->base; - init_array_type_source_node = container_type->base.source_node; - } else { - child_result_loc = parent_result_loc; - if (parent_result_loc->source_instruction != nullptr) { - init_array_type_source_node = parent_result_loc->source_instruction->base.source_node; - } else { - init_array_type_source_node = node; - } - } - - switch (kind) { - case ContainerInitKindStruct: { - IrInstSrc *container_ptr = ir_build_resolve_result(irb, scope, node, child_result_loc, - nullptr); - - size_t field_count = container_init_expr->entries.length; - IrInstSrcContainerInitFieldsField *fields = heap::c_allocator.allocate(field_count); - for (size_t i = 0; i < field_count; i += 1) { - AstNode *entry_node = container_init_expr->entries.at(i); - assert(entry_node->type == NodeTypeStructValueField); - - Buf *name = entry_node->data.struct_val_field.name; - AstNode *expr_node = entry_node->data.struct_val_field.expr; - - IrInstSrc *field_ptr = ir_build_field_ptr(irb, scope, entry_node, container_ptr, name, true); - ResultLocInstruction *result_loc_inst = heap::c_allocator.create(); - result_loc_inst->base.id = ResultLocIdInstruction; - result_loc_inst->base.source_instruction = field_ptr; - result_loc_inst->base.allow_write_through_const = true; - ir_ref_instruction(field_ptr, irb->current_basic_block); - ir_build_reset_result(irb, scope, expr_node, &result_loc_inst->base); - - IrInstSrc *expr_value = ir_gen_node_extra(irb, expr_node, scope, LValNone, - &result_loc_inst->base); - if (expr_value == irb->codegen->invalid_inst_src) - return expr_value; - - fields[i].name = name; - fields[i].source_node = entry_node; - fields[i].result_loc = field_ptr; - } - IrInstSrc *result = ir_build_container_init_fields(irb, scope, node, field_count, - fields, container_ptr); - - if (result_loc_cast != nullptr) { - result = ir_build_implicit_cast(irb, scope, node, result, result_loc_cast); - } - return ir_lval_wrap(irb, scope, result, lval, parent_result_loc); - } - case ContainerInitKindArray: { - size_t item_count = container_init_expr->entries.length; - - IrInstSrc *container_ptr = ir_build_resolve_result(irb, scope, node, child_result_loc, - nullptr); - - IrInstSrc **result_locs = heap::c_allocator.allocate(item_count); - for (size_t i = 0; i < item_count; i += 1) { - AstNode *expr_node = container_init_expr->entries.at(i); - - IrInstSrc *elem_index = ir_build_const_usize(irb, scope, expr_node, i); - IrInstSrc *elem_ptr = ir_build_elem_ptr(irb, scope, expr_node, container_ptr, - elem_index, false, PtrLenSingle, init_array_type_source_node); - ResultLocInstruction *result_loc_inst = heap::c_allocator.create(); - result_loc_inst->base.id = ResultLocIdInstruction; - result_loc_inst->base.source_instruction = elem_ptr; - result_loc_inst->base.allow_write_through_const = true; - ir_ref_instruction(elem_ptr, irb->current_basic_block); - ir_build_reset_result(irb, scope, expr_node, &result_loc_inst->base); - - IrInstSrc *expr_value = ir_gen_node_extra(irb, expr_node, scope, LValNone, - &result_loc_inst->base); - if (expr_value == irb->codegen->invalid_inst_src) - return expr_value; - - result_locs[i] = elem_ptr; - } - IrInstSrc *result = ir_build_container_init_list(irb, scope, node, item_count, - result_locs, container_ptr, init_array_type_source_node); - if (result_loc_cast != nullptr) { - result = ir_build_implicit_cast(irb, scope, node, result, result_loc_cast); - } - return ir_lval_wrap(irb, scope, result, lval, parent_result_loc); - } - } - zig_unreachable(); -} - -static ResultLocVar *ir_build_var_result_loc(IrBuilderSrc *irb, IrInstSrc *alloca, ZigVar *var) { - ResultLocVar *result_loc_var = heap::c_allocator.create(); - result_loc_var->base.id = ResultLocIdVar; - result_loc_var->base.source_instruction = alloca; - result_loc_var->base.allow_write_through_const = true; - result_loc_var->var = var; - - ir_build_reset_result(irb, alloca->base.scope, alloca->base.source_node, &result_loc_var->base); - - return result_loc_var; -} - -static ResultLocCast *ir_build_cast_result_loc(IrBuilderSrc *irb, IrInstSrc *dest_type, - ResultLoc *parent_result_loc) -{ - ResultLocCast *result_loc_cast = heap::c_allocator.create(); - result_loc_cast->base.id = ResultLocIdCast; - result_loc_cast->base.source_instruction = dest_type; - result_loc_cast->base.allow_write_through_const = parent_result_loc->allow_write_through_const; - ir_ref_instruction(dest_type, irb->current_basic_block); - result_loc_cast->parent = parent_result_loc; - - ir_build_reset_result(irb, dest_type->base.scope, dest_type->base.source_node, &result_loc_cast->base); - - return result_loc_cast; -} - -static void build_decl_var_and_init(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, ZigVar *var, - IrInstSrc *init, const char *name_hint, IrInstSrc *is_comptime) -{ - IrInstSrc *alloca = ir_build_alloca_src(irb, scope, source_node, nullptr, name_hint, is_comptime); - ResultLocVar *var_result_loc = ir_build_var_result_loc(irb, alloca, var); - ir_build_end_expr(irb, scope, source_node, init, &var_result_loc->base); - ir_build_var_decl_src(irb, scope, source_node, var, nullptr, alloca); -} - -static IrInstSrc *ir_gen_var_decl(IrBuilderSrc *irb, Scope *scope, AstNode *node) { - assert(node->type == NodeTypeVariableDeclaration); - - AstNodeVariableDeclaration *variable_declaration = &node->data.variable_declaration; - - if (buf_eql_str(variable_declaration->symbol, "_")) { - add_node_error(irb->codegen, node, buf_sprintf("`_` is not a declarable symbol")); - return irb->codegen->invalid_inst_src; - } - - // Used for the type expr and the align expr - Scope *comptime_scope = create_comptime_scope(irb->codegen, node, scope); - - IrInstSrc *type_instruction; - if (variable_declaration->type != nullptr) { - type_instruction = ir_gen_node(irb, variable_declaration->type, comptime_scope); - if (type_instruction == irb->codegen->invalid_inst_src) - return type_instruction; - } else { - type_instruction = nullptr; - } - - bool is_shadowable = false; - bool is_const = variable_declaration->is_const; - bool is_extern = variable_declaration->is_extern; - - bool is_comptime_scalar = ir_should_inline(irb->exec, scope) || variable_declaration->is_comptime; - IrInstSrc *is_comptime = ir_build_const_bool(irb, scope, node, is_comptime_scalar); - ZigVar *var = ir_create_var(irb, node, scope, variable_declaration->symbol, - is_const, is_const, is_shadowable, is_comptime); - // we detect IrInstSrcDeclVar in gen_block to make sure the next node - // is inside var->child_scope - - if (!is_extern && !variable_declaration->expr) { - var->var_type = irb->codegen->builtin_types.entry_invalid; - add_node_error(irb->codegen, node, buf_sprintf("variables must be initialized")); - return irb->codegen->invalid_inst_src; - } - - IrInstSrc *align_value = nullptr; - if (variable_declaration->align_expr != nullptr) { - align_value = ir_gen_node(irb, variable_declaration->align_expr, comptime_scope); - if (align_value == irb->codegen->invalid_inst_src) - return align_value; - } - - if (variable_declaration->section_expr != nullptr) { - add_node_error(irb->codegen, variable_declaration->section_expr, - buf_sprintf("cannot set section of local variable '%s'", buf_ptr(variable_declaration->symbol))); - } - - // Parser should ensure that this never happens - assert(variable_declaration->threadlocal_tok == nullptr); - - IrInstSrc *alloca = ir_build_alloca_src(irb, scope, node, align_value, - buf_ptr(variable_declaration->symbol), is_comptime); - - // Create a result location for the initialization expression. - ResultLocVar *result_loc_var = ir_build_var_result_loc(irb, alloca, var); - ResultLoc *init_result_loc; - ResultLocCast *result_loc_cast; - if (type_instruction != nullptr) { - result_loc_cast = ir_build_cast_result_loc(irb, type_instruction, &result_loc_var->base); - init_result_loc = &result_loc_cast->base; - } else { - result_loc_cast = nullptr; - init_result_loc = &result_loc_var->base; - } - - Scope *init_scope = is_comptime_scalar ? - create_comptime_scope(irb->codegen, variable_declaration->expr, scope) : scope; - - // Temporarily set the name of the IrExecutableSrc to the VariableDeclaration - // so that the struct or enum from the init expression inherits the name. - Buf *old_exec_name = irb->exec->name; - irb->exec->name = variable_declaration->symbol; - IrInstSrc *init_value = ir_gen_node_extra(irb, variable_declaration->expr, init_scope, - LValNone, init_result_loc); - irb->exec->name = old_exec_name; - - if (init_value == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - - if (result_loc_cast != nullptr) { - IrInstSrc *implicit_cast = ir_build_implicit_cast(irb, scope, init_value->base.source_node, - init_value, result_loc_cast); - ir_build_end_expr(irb, scope, node, implicit_cast, &result_loc_var->base); - } - - return ir_build_var_decl_src(irb, scope, node, var, align_value, alloca); -} - -static IrInstSrc *ir_gen_while_expr(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, - ResultLoc *result_loc) -{ - assert(node->type == NodeTypeWhileExpr); - - AstNode *continue_expr_node = node->data.while_expr.continue_expr; - AstNode *else_node = node->data.while_expr.else_node; - - IrBasicBlockSrc *cond_block = ir_create_basic_block(irb, scope, "WhileCond"); - IrBasicBlockSrc *body_block = ir_create_basic_block(irb, scope, "WhileBody"); - IrBasicBlockSrc *continue_block = continue_expr_node ? - ir_create_basic_block(irb, scope, "WhileContinue") : cond_block; - IrBasicBlockSrc *end_block = ir_create_basic_block(irb, scope, "WhileEnd"); - IrBasicBlockSrc *else_block = else_node ? - ir_create_basic_block(irb, scope, "WhileElse") : end_block; - - IrInstSrc *is_comptime = ir_build_const_bool(irb, scope, node, - ir_should_inline(irb->exec, scope) || node->data.while_expr.is_inline); - ir_build_br(irb, scope, node, cond_block, is_comptime); - - Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime); - Buf *var_symbol = node->data.while_expr.var_symbol; - Buf *err_symbol = node->data.while_expr.err_symbol; - if (err_symbol != nullptr) { - ir_set_cursor_at_end_and_append_block(irb, cond_block); - - Scope *payload_scope; - AstNode *symbol_node = node; // TODO make more accurate - ZigVar *payload_var; - if (var_symbol) { - // TODO make it an error to write to payload variable - payload_var = ir_create_var(irb, symbol_node, subexpr_scope, var_symbol, - true, false, false, is_comptime); - payload_scope = payload_var->child_scope; - } else { - payload_scope = subexpr_scope; - } - ScopeExpr *spill_scope = create_expr_scope(irb->codegen, node, payload_scope); - IrInstSrc *err_val_ptr = ir_gen_node_extra(irb, node->data.while_expr.condition, subexpr_scope, - LValPtr, nullptr); - if (err_val_ptr == irb->codegen->invalid_inst_src) - return err_val_ptr; - IrInstSrc *is_err = ir_build_test_err_src(irb, scope, node->data.while_expr.condition, err_val_ptr, - true, false); - IrBasicBlockSrc *after_cond_block = irb->current_basic_block; - IrInstSrc *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, scope, node)); - IrInstSrc *cond_br_inst; - if (!instr_is_unreachable(is_err)) { - cond_br_inst = ir_build_cond_br(irb, scope, node->data.while_expr.condition, is_err, - else_block, body_block, is_comptime); - cond_br_inst->is_gen = true; - } else { - // for the purposes of the source instruction to ir_build_result_peers - cond_br_inst = irb->current_basic_block->instruction_list.last(); - } - - ResultLocPeerParent *peer_parent = ir_build_result_peers(irb, cond_br_inst, end_block, result_loc, - is_comptime); - - ir_set_cursor_at_end_and_append_block(irb, body_block); - if (var_symbol) { - IrInstSrc *payload_ptr = ir_build_unwrap_err_payload_src(irb, &spill_scope->base, symbol_node, - err_val_ptr, false, false); - IrInstSrc *var_value = node->data.while_expr.var_is_ptr ? - payload_ptr : ir_build_load_ptr(irb, &spill_scope->base, symbol_node, payload_ptr); - build_decl_var_and_init(irb, payload_scope, symbol_node, payload_var, var_value, buf_ptr(var_symbol), is_comptime); - } - - ZigList incoming_values = {0}; - ZigList incoming_blocks = {0}; - - if (is_duplicate_label(irb->codegen, payload_scope, node, node->data.while_expr.name)) - return irb->codegen->invalid_inst_src; - - ScopeLoop *loop_scope = create_loop_scope(irb->codegen, node, payload_scope); - loop_scope->break_block = end_block; - loop_scope->continue_block = continue_block; - loop_scope->is_comptime = is_comptime; - loop_scope->incoming_blocks = &incoming_blocks; - loop_scope->incoming_values = &incoming_values; - loop_scope->lval = lval; - loop_scope->peer_parent = peer_parent; - loop_scope->spill_scope = spill_scope; - - // Note the body block of the loop is not the place that lval and result_loc are used - - // it's actually in break statements, handled similarly to return statements. - // That is why we set those values in loop_scope above and not in this ir_gen_node call. - IrInstSrc *body_result = ir_gen_node(irb, node->data.while_expr.body, &loop_scope->base); - if (body_result == irb->codegen->invalid_inst_src) - return body_result; - - if (loop_scope->name != nullptr && loop_scope->name_used == false) { - add_node_error(irb->codegen, node, buf_sprintf("unused while label")); - } - - if (!instr_is_unreachable(body_result)) { - ir_mark_gen(ir_build_check_statement_is_void(irb, payload_scope, node->data.while_expr.body, body_result)); - ir_mark_gen(ir_build_br(irb, payload_scope, node, continue_block, is_comptime)); - } - - if (continue_expr_node) { - ir_set_cursor_at_end_and_append_block(irb, continue_block); - IrInstSrc *expr_result = ir_gen_node(irb, continue_expr_node, payload_scope); - if (expr_result == irb->codegen->invalid_inst_src) - return expr_result; - if (!instr_is_unreachable(expr_result)) { - ir_mark_gen(ir_build_check_statement_is_void(irb, payload_scope, continue_expr_node, expr_result)); - ir_mark_gen(ir_build_br(irb, payload_scope, node, cond_block, is_comptime)); - } - } - - ir_set_cursor_at_end_and_append_block(irb, else_block); - assert(else_node != nullptr); - - // TODO make it an error to write to error variable - AstNode *err_symbol_node = else_node; // TODO make more accurate - ZigVar *err_var = ir_create_var(irb, err_symbol_node, scope, err_symbol, - true, false, false, is_comptime); - Scope *err_scope = err_var->child_scope; - IrInstSrc *err_ptr = ir_build_unwrap_err_code_src(irb, err_scope, err_symbol_node, err_val_ptr); - IrInstSrc *err_value = ir_build_load_ptr(irb, err_scope, err_symbol_node, err_ptr); - build_decl_var_and_init(irb, err_scope, err_symbol_node, err_var, err_value, buf_ptr(err_symbol), is_comptime); - - if (peer_parent->peers.length != 0) { - peer_parent->peers.last()->next_bb = else_block; - } - ResultLocPeer *peer_result = create_peer_result(peer_parent); - peer_parent->peers.append(peer_result); - IrInstSrc *else_result = ir_gen_node_extra(irb, else_node, err_scope, lval, &peer_result->base); - if (else_result == irb->codegen->invalid_inst_src) - return else_result; - if (!instr_is_unreachable(else_result)) - ir_mark_gen(ir_build_br(irb, scope, node, end_block, is_comptime)); - IrBasicBlockSrc *after_else_block = irb->current_basic_block; - ir_set_cursor_at_end_and_append_block(irb, end_block); - if (else_result) { - incoming_blocks.append(after_else_block); - incoming_values.append(else_result); - } else { - incoming_blocks.append(after_cond_block); - incoming_values.append(void_else_result); - } - if (peer_parent->peers.length != 0) { - peer_parent->peers.last()->next_bb = end_block; - } - - IrInstSrc *phi = ir_build_phi(irb, scope, node, incoming_blocks.length, - incoming_blocks.items, incoming_values.items, peer_parent); - return ir_expr_wrap(irb, scope, phi, result_loc); - } else if (var_symbol != nullptr) { - ir_set_cursor_at_end_and_append_block(irb, cond_block); - Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime); - // TODO make it an error to write to payload variable - AstNode *symbol_node = node; // TODO make more accurate - - ZigVar *payload_var = ir_create_var(irb, symbol_node, subexpr_scope, var_symbol, - true, false, false, is_comptime); - Scope *child_scope = payload_var->child_scope; - ScopeExpr *spill_scope = create_expr_scope(irb->codegen, node, child_scope); - IrInstSrc *maybe_val_ptr = ir_gen_node_extra(irb, node->data.while_expr.condition, subexpr_scope, - LValPtr, nullptr); - if (maybe_val_ptr == irb->codegen->invalid_inst_src) - return maybe_val_ptr; - IrInstSrc *maybe_val = ir_build_load_ptr(irb, scope, node->data.while_expr.condition, maybe_val_ptr); - IrInstSrc *is_non_null = ir_build_test_non_null_src(irb, scope, node->data.while_expr.condition, maybe_val); - IrBasicBlockSrc *after_cond_block = irb->current_basic_block; - IrInstSrc *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, scope, node)); - IrInstSrc *cond_br_inst; - if (!instr_is_unreachable(is_non_null)) { - cond_br_inst = ir_build_cond_br(irb, scope, node->data.while_expr.condition, is_non_null, - body_block, else_block, is_comptime); - cond_br_inst->is_gen = true; - } else { - // for the purposes of the source instruction to ir_build_result_peers - cond_br_inst = irb->current_basic_block->instruction_list.last(); - } - - ResultLocPeerParent *peer_parent = ir_build_result_peers(irb, cond_br_inst, end_block, result_loc, - is_comptime); - - ir_set_cursor_at_end_and_append_block(irb, body_block); - IrInstSrc *payload_ptr = ir_build_optional_unwrap_ptr(irb, &spill_scope->base, symbol_node, maybe_val_ptr, false); - IrInstSrc *var_value = node->data.while_expr.var_is_ptr ? - payload_ptr : ir_build_load_ptr(irb, &spill_scope->base, symbol_node, payload_ptr); - build_decl_var_and_init(irb, child_scope, symbol_node, payload_var, var_value, buf_ptr(var_symbol), is_comptime); - - ZigList incoming_values = {0}; - ZigList incoming_blocks = {0}; - - if (is_duplicate_label(irb->codegen, child_scope, node, node->data.while_expr.name)) - return irb->codegen->invalid_inst_src; - - ScopeLoop *loop_scope = create_loop_scope(irb->codegen, node, child_scope); - loop_scope->break_block = end_block; - loop_scope->continue_block = continue_block; - loop_scope->is_comptime = is_comptime; - loop_scope->incoming_blocks = &incoming_blocks; - loop_scope->incoming_values = &incoming_values; - loop_scope->lval = lval; - loop_scope->peer_parent = peer_parent; - loop_scope->spill_scope = spill_scope; - - // Note the body block of the loop is not the place that lval and result_loc are used - - // it's actually in break statements, handled similarly to return statements. - // That is why we set those values in loop_scope above and not in this ir_gen_node call. - IrInstSrc *body_result = ir_gen_node(irb, node->data.while_expr.body, &loop_scope->base); - if (body_result == irb->codegen->invalid_inst_src) - return body_result; - - if (loop_scope->name != nullptr && loop_scope->name_used == false) { - add_node_error(irb->codegen, node, buf_sprintf("unused while label")); - } - - if (!instr_is_unreachable(body_result)) { - ir_mark_gen(ir_build_check_statement_is_void(irb, child_scope, node->data.while_expr.body, body_result)); - ir_mark_gen(ir_build_br(irb, child_scope, node, continue_block, is_comptime)); - } - - if (continue_expr_node) { - ir_set_cursor_at_end_and_append_block(irb, continue_block); - IrInstSrc *expr_result = ir_gen_node(irb, continue_expr_node, child_scope); - if (expr_result == irb->codegen->invalid_inst_src) - return expr_result; - if (!instr_is_unreachable(expr_result)) { - ir_mark_gen(ir_build_check_statement_is_void(irb, child_scope, continue_expr_node, expr_result)); - ir_mark_gen(ir_build_br(irb, child_scope, node, cond_block, is_comptime)); - } - } - - IrInstSrc *else_result = nullptr; - if (else_node) { - ir_set_cursor_at_end_and_append_block(irb, else_block); - - if (peer_parent->peers.length != 0) { - peer_parent->peers.last()->next_bb = else_block; - } - ResultLocPeer *peer_result = create_peer_result(peer_parent); - peer_parent->peers.append(peer_result); - else_result = ir_gen_node_extra(irb, else_node, scope, lval, &peer_result->base); - if (else_result == irb->codegen->invalid_inst_src) - return else_result; - if (!instr_is_unreachable(else_result)) - ir_mark_gen(ir_build_br(irb, scope, node, end_block, is_comptime)); - } - IrBasicBlockSrc *after_else_block = irb->current_basic_block; - ir_set_cursor_at_end_and_append_block(irb, end_block); - if (else_result) { - incoming_blocks.append(after_else_block); - incoming_values.append(else_result); - } else { - incoming_blocks.append(after_cond_block); - incoming_values.append(void_else_result); - } - if (peer_parent->peers.length != 0) { - peer_parent->peers.last()->next_bb = end_block; - } - - IrInstSrc *phi = ir_build_phi(irb, scope, node, incoming_blocks.length, - incoming_blocks.items, incoming_values.items, peer_parent); - return ir_expr_wrap(irb, scope, phi, result_loc); - } else { - ir_set_cursor_at_end_and_append_block(irb, cond_block); - IrInstSrc *cond_val = ir_gen_node(irb, node->data.while_expr.condition, scope); - if (cond_val == irb->codegen->invalid_inst_src) - return cond_val; - IrBasicBlockSrc *after_cond_block = irb->current_basic_block; - IrInstSrc *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, scope, node)); - IrInstSrc *cond_br_inst; - if (!instr_is_unreachable(cond_val)) { - cond_br_inst = ir_build_cond_br(irb, scope, node->data.while_expr.condition, cond_val, - body_block, else_block, is_comptime); - cond_br_inst->is_gen = true; - } else { - // for the purposes of the source instruction to ir_build_result_peers - cond_br_inst = irb->current_basic_block->instruction_list.last(); - } - - ResultLocPeerParent *peer_parent = ir_build_result_peers(irb, cond_br_inst, end_block, result_loc, - is_comptime); - ir_set_cursor_at_end_and_append_block(irb, body_block); - - ZigList incoming_values = {0}; - ZigList incoming_blocks = {0}; - - Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime); - - if (is_duplicate_label(irb->codegen, subexpr_scope, node, node->data.while_expr.name)) - return irb->codegen->invalid_inst_src; - - ScopeLoop *loop_scope = create_loop_scope(irb->codegen, node, subexpr_scope); - loop_scope->break_block = end_block; - loop_scope->continue_block = continue_block; - loop_scope->is_comptime = is_comptime; - loop_scope->incoming_blocks = &incoming_blocks; - loop_scope->incoming_values = &incoming_values; - loop_scope->lval = lval; - loop_scope->peer_parent = peer_parent; - - // Note the body block of the loop is not the place that lval and result_loc are used - - // it's actually in break statements, handled similarly to return statements. - // That is why we set those values in loop_scope above and not in this ir_gen_node call. - IrInstSrc *body_result = ir_gen_node(irb, node->data.while_expr.body, &loop_scope->base); - if (body_result == irb->codegen->invalid_inst_src) - return body_result; - - if (loop_scope->name != nullptr && loop_scope->name_used == false) { - add_node_error(irb->codegen, node, buf_sprintf("unused while label")); - } - - if (!instr_is_unreachable(body_result)) { - ir_mark_gen(ir_build_check_statement_is_void(irb, scope, node->data.while_expr.body, body_result)); - ir_mark_gen(ir_build_br(irb, scope, node, continue_block, is_comptime)); - } - - if (continue_expr_node) { - ir_set_cursor_at_end_and_append_block(irb, continue_block); - IrInstSrc *expr_result = ir_gen_node(irb, continue_expr_node, subexpr_scope); - if (expr_result == irb->codegen->invalid_inst_src) - return expr_result; - if (!instr_is_unreachable(expr_result)) { - ir_mark_gen(ir_build_check_statement_is_void(irb, scope, continue_expr_node, expr_result)); - ir_mark_gen(ir_build_br(irb, scope, node, cond_block, is_comptime)); - } - } - - IrInstSrc *else_result = nullptr; - if (else_node) { - ir_set_cursor_at_end_and_append_block(irb, else_block); - - if (peer_parent->peers.length != 0) { - peer_parent->peers.last()->next_bb = else_block; - } - ResultLocPeer *peer_result = create_peer_result(peer_parent); - peer_parent->peers.append(peer_result); - - else_result = ir_gen_node_extra(irb, else_node, subexpr_scope, lval, &peer_result->base); - if (else_result == irb->codegen->invalid_inst_src) - return else_result; - if (!instr_is_unreachable(else_result)) - ir_mark_gen(ir_build_br(irb, scope, node, end_block, is_comptime)); - } - IrBasicBlockSrc *after_else_block = irb->current_basic_block; - ir_set_cursor_at_end_and_append_block(irb, end_block); - if (else_result) { - incoming_blocks.append(after_else_block); - incoming_values.append(else_result); - } else { - incoming_blocks.append(after_cond_block); - incoming_values.append(void_else_result); - } - if (peer_parent->peers.length != 0) { - peer_parent->peers.last()->next_bb = end_block; - } - - IrInstSrc *phi = ir_build_phi(irb, scope, node, incoming_blocks.length, - incoming_blocks.items, incoming_values.items, peer_parent); - return ir_expr_wrap(irb, scope, phi, result_loc); - } -} - -static IrInstSrc *ir_gen_for_expr(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node, LVal lval, - ResultLoc *result_loc) -{ - assert(node->type == NodeTypeForExpr); - - AstNode *array_node = node->data.for_expr.array_expr; - AstNode *elem_node = node->data.for_expr.elem_node; - AstNode *index_node = node->data.for_expr.index_node; - AstNode *body_node = node->data.for_expr.body; - AstNode *else_node = node->data.for_expr.else_node; - - if (!elem_node) { - add_node_error(irb->codegen, node, buf_sprintf("for loop expression missing element parameter")); - return irb->codegen->invalid_inst_src; - } - assert(elem_node->type == NodeTypeSymbol); - - ScopeExpr *spill_scope = create_expr_scope(irb->codegen, node, parent_scope); - - IrInstSrc *array_val_ptr = ir_gen_node_extra(irb, array_node, &spill_scope->base, LValPtr, nullptr); - if (array_val_ptr == irb->codegen->invalid_inst_src) - return array_val_ptr; - - IrInstSrc *is_comptime = ir_build_const_bool(irb, parent_scope, node, - ir_should_inline(irb->exec, parent_scope) || node->data.for_expr.is_inline); - - AstNode *index_var_source_node; - ZigVar *index_var; - const char *index_var_name; - if (index_node) { - index_var_source_node = index_node; - Buf *index_var_name_buf = index_node->data.symbol_expr.symbol; - index_var = ir_create_var(irb, index_node, parent_scope, index_var_name_buf, true, false, false, is_comptime); - index_var_name = buf_ptr(index_var_name_buf); - } else { - index_var_source_node = node; - index_var = ir_create_var(irb, node, parent_scope, nullptr, true, false, true, is_comptime); - index_var_name = "i"; - } - - IrInstSrc *zero = ir_build_const_usize(irb, parent_scope, node, 0); - build_decl_var_and_init(irb, parent_scope, index_var_source_node, index_var, zero, index_var_name, is_comptime); - parent_scope = index_var->child_scope; - - IrInstSrc *one = ir_build_const_usize(irb, parent_scope, node, 1); - IrInstSrc *index_ptr = ir_build_var_ptr(irb, parent_scope, node, index_var); - - - IrBasicBlockSrc *cond_block = ir_create_basic_block(irb, parent_scope, "ForCond"); - IrBasicBlockSrc *body_block = ir_create_basic_block(irb, parent_scope, "ForBody"); - IrBasicBlockSrc *end_block = ir_create_basic_block(irb, parent_scope, "ForEnd"); - IrBasicBlockSrc *else_block = else_node ? ir_create_basic_block(irb, parent_scope, "ForElse") : end_block; - IrBasicBlockSrc *continue_block = ir_create_basic_block(irb, parent_scope, "ForContinue"); - - Buf *len_field_name = buf_create_from_str("len"); - IrInstSrc *len_ref = ir_build_field_ptr(irb, parent_scope, node, array_val_ptr, len_field_name, false); - IrInstSrc *len_val = ir_build_load_ptr(irb, &spill_scope->base, node, len_ref); - ir_build_br(irb, parent_scope, node, cond_block, is_comptime); - - ir_set_cursor_at_end_and_append_block(irb, cond_block); - IrInstSrc *index_val = ir_build_load_ptr(irb, &spill_scope->base, node, index_ptr); - IrInstSrc *cond = ir_build_bin_op(irb, parent_scope, node, IrBinOpCmpLessThan, index_val, len_val, false); - IrBasicBlockSrc *after_cond_block = irb->current_basic_block; - IrInstSrc *void_else_value = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, parent_scope, node)); - IrInstSrc *cond_br_inst = ir_mark_gen(ir_build_cond_br(irb, parent_scope, node, cond, - body_block, else_block, is_comptime)); - - ResultLocPeerParent *peer_parent = ir_build_result_peers(irb, cond_br_inst, end_block, result_loc, is_comptime); - - ir_set_cursor_at_end_and_append_block(irb, body_block); - IrInstSrc *elem_ptr = ir_build_elem_ptr(irb, &spill_scope->base, node, array_val_ptr, index_val, - false, PtrLenSingle, nullptr); - // TODO make it an error to write to element variable or i variable. - Buf *elem_var_name = elem_node->data.symbol_expr.symbol; - ZigVar *elem_var = ir_create_var(irb, elem_node, parent_scope, elem_var_name, true, false, false, is_comptime); - Scope *child_scope = elem_var->child_scope; - - IrInstSrc *elem_value = node->data.for_expr.elem_is_ptr ? - elem_ptr : ir_build_load_ptr(irb, &spill_scope->base, elem_node, elem_ptr); - build_decl_var_and_init(irb, parent_scope, elem_node, elem_var, elem_value, buf_ptr(elem_var_name), is_comptime); - - if (is_duplicate_label(irb->codegen, child_scope, node, node->data.for_expr.name)) - return irb->codegen->invalid_inst_src; - - ZigList incoming_values = {0}; - ZigList incoming_blocks = {0}; - ScopeLoop *loop_scope = create_loop_scope(irb->codegen, node, child_scope); - loop_scope->break_block = end_block; - loop_scope->continue_block = continue_block; - loop_scope->is_comptime = is_comptime; - loop_scope->incoming_blocks = &incoming_blocks; - loop_scope->incoming_values = &incoming_values; - loop_scope->lval = LValNone; - loop_scope->peer_parent = peer_parent; - loop_scope->spill_scope = spill_scope; - - // Note the body block of the loop is not the place that lval and result_loc are used - - // it's actually in break statements, handled similarly to return statements. - // That is why we set those values in loop_scope above and not in this ir_gen_node call. - IrInstSrc *body_result = ir_gen_node(irb, body_node, &loop_scope->base); - if (body_result == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - - if (loop_scope->name != nullptr && loop_scope->name_used == false) { - add_node_error(irb->codegen, node, buf_sprintf("unused for label")); - } - - if (!instr_is_unreachable(body_result)) { - ir_mark_gen(ir_build_check_statement_is_void(irb, child_scope, node->data.for_expr.body, body_result)); - ir_mark_gen(ir_build_br(irb, child_scope, node, continue_block, is_comptime)); - } - - ir_set_cursor_at_end_and_append_block(irb, continue_block); - IrInstSrc *new_index_val = ir_build_bin_op(irb, child_scope, node, IrBinOpAdd, index_val, one, false); - ir_build_store_ptr(irb, child_scope, node, index_ptr, new_index_val)->allow_write_through_const = true; - ir_build_br(irb, child_scope, node, cond_block, is_comptime); - - IrInstSrc *else_result = nullptr; - if (else_node) { - ir_set_cursor_at_end_and_append_block(irb, else_block); - - if (peer_parent->peers.length != 0) { - peer_parent->peers.last()->next_bb = else_block; - } - ResultLocPeer *peer_result = create_peer_result(peer_parent); - peer_parent->peers.append(peer_result); - else_result = ir_gen_node_extra(irb, else_node, parent_scope, LValNone, &peer_result->base); - if (else_result == irb->codegen->invalid_inst_src) - return else_result; - if (!instr_is_unreachable(else_result)) - ir_mark_gen(ir_build_br(irb, parent_scope, node, end_block, is_comptime)); - } - IrBasicBlockSrc *after_else_block = irb->current_basic_block; - ir_set_cursor_at_end_and_append_block(irb, end_block); - - if (else_result) { - incoming_blocks.append(after_else_block); - incoming_values.append(else_result); - } else { - incoming_blocks.append(after_cond_block); - incoming_values.append(void_else_value); - } - if (peer_parent->peers.length != 0) { - peer_parent->peers.last()->next_bb = end_block; - } - - IrInstSrc *phi = ir_build_phi(irb, parent_scope, node, incoming_blocks.length, - incoming_blocks.items, incoming_values.items, peer_parent); - return ir_lval_wrap(irb, parent_scope, phi, lval, result_loc); -} - -static IrInstSrc *ir_gen_bool_literal(IrBuilderSrc *irb, Scope *scope, AstNode *node) { - assert(node->type == NodeTypeBoolLiteral); - return ir_build_const_bool(irb, scope, node, node->data.bool_literal.value); -} - -static IrInstSrc *ir_gen_enum_literal(IrBuilderSrc *irb, Scope *scope, AstNode *node) { - assert(node->type == NodeTypeEnumLiteral); - Buf *name = &node->data.enum_literal.identifier->data.str_lit.str; - return ir_build_const_enum_literal(irb, scope, node, name); -} - -static IrInstSrc *ir_gen_string_literal(IrBuilderSrc *irb, Scope *scope, AstNode *node) { - assert(node->type == NodeTypeStringLiteral); - - return ir_build_const_str_lit(irb, scope, node, node->data.string_literal.buf); -} - -static IrInstSrc *ir_gen_array_type(IrBuilderSrc *irb, Scope *scope, AstNode *node) { - assert(node->type == NodeTypeArrayType); - - AstNode *size_node = node->data.array_type.size; - AstNode *child_type_node = node->data.array_type.child_type; - bool is_const = node->data.array_type.is_const; - bool is_volatile = node->data.array_type.is_volatile; - bool is_allow_zero = node->data.array_type.allow_zero_token != nullptr; - AstNode *sentinel_expr = node->data.array_type.sentinel; - AstNode *align_expr = node->data.array_type.align_expr; - - Scope *comptime_scope = create_comptime_scope(irb->codegen, node, scope); - - IrInstSrc *sentinel; - if (sentinel_expr != nullptr) { - sentinel = ir_gen_node(irb, sentinel_expr, comptime_scope); - if (sentinel == irb->codegen->invalid_inst_src) - return sentinel; - } else { - sentinel = nullptr; - } - - if (size_node) { - if (is_const) { - add_node_error(irb->codegen, node, buf_create_from_str("const qualifier invalid on array type")); - return irb->codegen->invalid_inst_src; - } - if (is_volatile) { - add_node_error(irb->codegen, node, buf_create_from_str("volatile qualifier invalid on array type")); - return irb->codegen->invalid_inst_src; - } - if (is_allow_zero) { - add_node_error(irb->codegen, node, buf_create_from_str("allowzero qualifier invalid on array type")); - return irb->codegen->invalid_inst_src; - } - if (align_expr != nullptr) { - add_node_error(irb->codegen, node, buf_create_from_str("align qualifier invalid on array type")); - return irb->codegen->invalid_inst_src; - } - - IrInstSrc *size_value = ir_gen_node(irb, size_node, comptime_scope); - if (size_value == irb->codegen->invalid_inst_src) - return size_value; - - IrInstSrc *child_type = ir_gen_node(irb, child_type_node, comptime_scope); - if (child_type == irb->codegen->invalid_inst_src) - return child_type; - - return ir_build_array_type(irb, scope, node, size_value, sentinel, child_type); - } else { - IrInstSrc *align_value; - if (align_expr != nullptr) { - align_value = ir_gen_node(irb, align_expr, comptime_scope); - if (align_value == irb->codegen->invalid_inst_src) - return align_value; - } else { - align_value = nullptr; - } - - IrInstSrc *child_type = ir_gen_node(irb, child_type_node, comptime_scope); - if (child_type == irb->codegen->invalid_inst_src) - return child_type; - - return ir_build_slice_type(irb, scope, node, child_type, is_const, is_volatile, sentinel, - align_value, is_allow_zero); - } -} - -static IrInstSrc *ir_gen_anyframe_type(IrBuilderSrc *irb, Scope *scope, AstNode *node) { - assert(node->type == NodeTypeAnyFrameType); - - AstNode *payload_type_node = node->data.anyframe_type.payload_type; - IrInstSrc *payload_type_value = nullptr; - - if (payload_type_node != nullptr) { - payload_type_value = ir_gen_node(irb, payload_type_node, scope); - if (payload_type_value == irb->codegen->invalid_inst_src) - return payload_type_value; - - } - - return ir_build_anyframe_type(irb, scope, node, payload_type_value); -} - -static IrInstSrc *ir_gen_undefined_literal(IrBuilderSrc *irb, Scope *scope, AstNode *node) { - assert(node->type == NodeTypeUndefinedLiteral); - return ir_build_const_undefined(irb, scope, node); -} - static Error parse_asm_template(IrAnalyze *ira, AstNode *source_node, Buf *asm_template, ZigList *tok_list) { @@ -8894,1030 +2426,6 @@ static Error parse_asm_template(IrAnalyze *ira, AstNode *source_node, Buf *asm_t return ErrorNone; } -static size_t find_asm_index(CodeGen *g, AstNode *node, AsmToken *tok, Buf *src_template) { - const char *ptr = buf_ptr(src_template) + tok->start + 2; - size_t len = tok->end - tok->start - 2; - size_t result = 0; - for (size_t i = 0; i < node->data.asm_expr.output_list.length; i += 1, result += 1) { - AsmOutput *asm_output = node->data.asm_expr.output_list.at(i); - if (buf_eql_mem(asm_output->asm_symbolic_name, ptr, len)) { - return result; - } - } - for (size_t i = 0; i < node->data.asm_expr.input_list.length; i += 1, result += 1) { - AsmInput *asm_input = node->data.asm_expr.input_list.at(i); - if (buf_eql_mem(asm_input->asm_symbolic_name, ptr, len)) { - return result; - } - } - return SIZE_MAX; -} - -static IrInstSrc *ir_gen_asm_expr(IrBuilderSrc *irb, Scope *scope, AstNode *node) { - assert(node->type == NodeTypeAsmExpr); - AstNodeAsmExpr *asm_expr = &node->data.asm_expr; - - IrInstSrc *asm_template = ir_gen_node(irb, asm_expr->asm_template, scope); - if (asm_template == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - - bool is_volatile = asm_expr->volatile_token != nullptr; - bool in_fn_scope = (scope_fn_entry(scope) != nullptr); - - if (!in_fn_scope) { - if (is_volatile) { - add_token_error(irb->codegen, node->owner, asm_expr->volatile_token, - buf_sprintf("volatile is meaningless on global assembly")); - return irb->codegen->invalid_inst_src; - } - - if (asm_expr->output_list.length != 0 || asm_expr->input_list.length != 0 || - asm_expr->clobber_list.length != 0) - { - add_node_error(irb->codegen, node, - buf_sprintf("global assembly cannot have inputs, outputs, or clobbers")); - return irb->codegen->invalid_inst_src; - } - - return ir_build_asm_src(irb, scope, node, asm_template, nullptr, nullptr, - nullptr, 0, is_volatile, true); - } - - IrInstSrc **input_list = heap::c_allocator.allocate(asm_expr->input_list.length); - IrInstSrc **output_types = heap::c_allocator.allocate(asm_expr->output_list.length); - ZigVar **output_vars = heap::c_allocator.allocate(asm_expr->output_list.length); - size_t return_count = 0; - if (!is_volatile && asm_expr->output_list.length == 0) { - add_node_error(irb->codegen, node, - buf_sprintf("assembly expression with no output must be marked volatile")); - return irb->codegen->invalid_inst_src; - } - for (size_t i = 0; i < asm_expr->output_list.length; i += 1) { - AsmOutput *asm_output = asm_expr->output_list.at(i); - if (asm_output->return_type) { - return_count += 1; - - IrInstSrc *return_type = ir_gen_node(irb, asm_output->return_type, scope); - if (return_type == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - if (return_count > 1) { - add_node_error(irb->codegen, node, - buf_sprintf("inline assembly allows up to one output value")); - return irb->codegen->invalid_inst_src; - } - output_types[i] = return_type; - } else { - Buf *variable_name = asm_output->variable_name; - // TODO there is some duplication here with ir_gen_symbol. I need to do a full audit of how - // inline assembly works. https://github.com/ziglang/zig/issues/215 - ZigVar *var = find_variable(irb->codegen, scope, variable_name, nullptr); - if (var) { - output_vars[i] = var; - } else { - add_node_error(irb->codegen, node, - buf_sprintf("use of undeclared identifier '%s'", buf_ptr(variable_name))); - return irb->codegen->invalid_inst_src; - } - } - - const char modifier = *buf_ptr(asm_output->constraint); - if (modifier != '=') { - add_node_error(irb->codegen, node, - buf_sprintf("invalid modifier starting output constraint for '%s': '%c', only '=' is supported." - " Compiler TODO: see https://github.com/ziglang/zig/issues/215", - buf_ptr(asm_output->asm_symbolic_name), modifier)); - return irb->codegen->invalid_inst_src; - } - } - for (size_t i = 0; i < asm_expr->input_list.length; i += 1) { - AsmInput *asm_input = asm_expr->input_list.at(i); - IrInstSrc *input_value = ir_gen_node(irb, asm_input->expr, scope); - if (input_value == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - - input_list[i] = input_value; - } - - return ir_build_asm_src(irb, scope, node, asm_template, input_list, output_types, - output_vars, return_count, is_volatile, false); -} - -static IrInstSrc *ir_gen_if_optional_expr(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, - ResultLoc *result_loc) -{ - assert(node->type == NodeTypeIfOptional); - - Buf *var_symbol = node->data.test_expr.var_symbol; - AstNode *expr_node = node->data.test_expr.target_node; - AstNode *then_node = node->data.test_expr.then_node; - AstNode *else_node = node->data.test_expr.else_node; - bool var_is_ptr = node->data.test_expr.var_is_ptr; - - ScopeExpr *spill_scope = create_expr_scope(irb->codegen, expr_node, scope); - spill_scope->spill_harder = true; - - IrInstSrc *maybe_val_ptr = ir_gen_node_extra(irb, expr_node, &spill_scope->base, LValPtr, nullptr); - if (maybe_val_ptr == irb->codegen->invalid_inst_src) - return maybe_val_ptr; - - IrInstSrc *maybe_val = ir_build_load_ptr(irb, scope, node, maybe_val_ptr); - IrInstSrc *is_non_null = ir_build_test_non_null_src(irb, scope, node, maybe_val); - - IrBasicBlockSrc *then_block = ir_create_basic_block(irb, scope, "OptionalThen"); - IrBasicBlockSrc *else_block = ir_create_basic_block(irb, scope, "OptionalElse"); - IrBasicBlockSrc *endif_block = ir_create_basic_block(irb, scope, "OptionalEndIf"); - - IrInstSrc *is_comptime; - if (ir_should_inline(irb->exec, scope)) { - is_comptime = ir_build_const_bool(irb, scope, node, true); - } else { - is_comptime = ir_build_test_comptime(irb, scope, node, is_non_null); - } - IrInstSrc *cond_br_inst = ir_build_cond_br(irb, scope, node, is_non_null, - then_block, else_block, is_comptime); - - ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, else_block, endif_block, - result_loc, is_comptime); - - ir_set_cursor_at_end_and_append_block(irb, then_block); - - Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, &spill_scope->base, is_comptime); - Scope *var_scope; - if (var_symbol) { - bool is_shadowable = false; - bool is_const = true; - ZigVar *var = ir_create_var(irb, node, subexpr_scope, - var_symbol, is_const, is_const, is_shadowable, is_comptime); - - IrInstSrc *payload_ptr = ir_build_optional_unwrap_ptr(irb, subexpr_scope, node, maybe_val_ptr, false); - IrInstSrc *var_value = var_is_ptr ? - payload_ptr : ir_build_load_ptr(irb, &spill_scope->base, node, payload_ptr); - build_decl_var_and_init(irb, subexpr_scope, node, var, var_value, buf_ptr(var_symbol), is_comptime); - var_scope = var->child_scope; - } else { - var_scope = subexpr_scope; - } - IrInstSrc *then_expr_result = ir_gen_node_extra(irb, then_node, var_scope, lval, - &peer_parent->peers.at(0)->base); - if (then_expr_result == irb->codegen->invalid_inst_src) - return then_expr_result; - IrBasicBlockSrc *after_then_block = irb->current_basic_block; - if (!instr_is_unreachable(then_expr_result)) - ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime)); - - ir_set_cursor_at_end_and_append_block(irb, else_block); - IrInstSrc *else_expr_result; - if (else_node) { - else_expr_result = ir_gen_node_extra(irb, else_node, subexpr_scope, lval, &peer_parent->peers.at(1)->base); - if (else_expr_result == irb->codegen->invalid_inst_src) - return else_expr_result; - } else { - else_expr_result = ir_build_const_void(irb, scope, node); - ir_build_end_expr(irb, scope, node, else_expr_result, &peer_parent->peers.at(1)->base); - } - IrBasicBlockSrc *after_else_block = irb->current_basic_block; - if (!instr_is_unreachable(else_expr_result)) - ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime)); - - ir_set_cursor_at_end_and_append_block(irb, endif_block); - IrInstSrc **incoming_values = heap::c_allocator.allocate(2); - incoming_values[0] = then_expr_result; - incoming_values[1] = else_expr_result; - IrBasicBlockSrc **incoming_blocks = heap::c_allocator.allocate(2); - incoming_blocks[0] = after_then_block; - incoming_blocks[1] = after_else_block; - - IrInstSrc *phi = ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, peer_parent); - return ir_expr_wrap(irb, scope, phi, result_loc); -} - -static IrInstSrc *ir_gen_if_err_expr(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, - ResultLoc *result_loc) -{ - assert(node->type == NodeTypeIfErrorExpr); - - AstNode *target_node = node->data.if_err_expr.target_node; - AstNode *then_node = node->data.if_err_expr.then_node; - AstNode *else_node = node->data.if_err_expr.else_node; - bool var_is_ptr = node->data.if_err_expr.var_is_ptr; - bool var_is_const = true; - Buf *var_symbol = node->data.if_err_expr.var_symbol; - Buf *err_symbol = node->data.if_err_expr.err_symbol; - - IrInstSrc *err_val_ptr = ir_gen_node_extra(irb, target_node, scope, LValPtr, nullptr); - if (err_val_ptr == irb->codegen->invalid_inst_src) - return err_val_ptr; - - IrInstSrc *err_val = ir_build_load_ptr(irb, scope, node, err_val_ptr); - IrInstSrc *is_err = ir_build_test_err_src(irb, scope, node, err_val_ptr, true, false); - - IrBasicBlockSrc *ok_block = ir_create_basic_block(irb, scope, "TryOk"); - IrBasicBlockSrc *else_block = ir_create_basic_block(irb, scope, "TryElse"); - IrBasicBlockSrc *endif_block = ir_create_basic_block(irb, scope, "TryEnd"); - - bool force_comptime = ir_should_inline(irb->exec, scope); - IrInstSrc *is_comptime = force_comptime ? ir_build_const_bool(irb, scope, node, true) : ir_build_test_comptime(irb, scope, node, is_err); - IrInstSrc *cond_br_inst = ir_build_cond_br(irb, scope, node, is_err, else_block, ok_block, is_comptime); - - ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, else_block, endif_block, - result_loc, is_comptime); - - ir_set_cursor_at_end_and_append_block(irb, ok_block); - - Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime); - Scope *var_scope; - if (var_symbol) { - bool is_shadowable = false; - IrInstSrc *var_is_comptime = force_comptime ? ir_build_const_bool(irb, subexpr_scope, node, true) : ir_build_test_comptime(irb, subexpr_scope, node, err_val); - ZigVar *var = ir_create_var(irb, node, subexpr_scope, - var_symbol, var_is_const, var_is_const, is_shadowable, var_is_comptime); - - IrInstSrc *payload_ptr = ir_build_unwrap_err_payload_src(irb, subexpr_scope, node, err_val_ptr, false, false); - IrInstSrc *var_value = var_is_ptr ? - payload_ptr : ir_build_load_ptr(irb, subexpr_scope, node, payload_ptr); - build_decl_var_and_init(irb, subexpr_scope, node, var, var_value, buf_ptr(var_symbol), var_is_comptime); - var_scope = var->child_scope; - } else { - var_scope = subexpr_scope; - } - IrInstSrc *then_expr_result = ir_gen_node_extra(irb, then_node, var_scope, lval, - &peer_parent->peers.at(0)->base); - if (then_expr_result == irb->codegen->invalid_inst_src) - return then_expr_result; - IrBasicBlockSrc *after_then_block = irb->current_basic_block; - if (!instr_is_unreachable(then_expr_result)) - ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime)); - - ir_set_cursor_at_end_and_append_block(irb, else_block); - - IrInstSrc *else_expr_result; - if (else_node) { - Scope *err_var_scope; - if (err_symbol) { - bool is_shadowable = false; - bool is_const = true; - ZigVar *var = ir_create_var(irb, node, subexpr_scope, - err_symbol, is_const, is_const, is_shadowable, is_comptime); - - IrInstSrc *err_ptr = ir_build_unwrap_err_code_src(irb, subexpr_scope, node, err_val_ptr); - IrInstSrc *err_value = ir_build_load_ptr(irb, subexpr_scope, node, err_ptr); - build_decl_var_and_init(irb, subexpr_scope, node, var, err_value, buf_ptr(err_symbol), is_comptime); - err_var_scope = var->child_scope; - } else { - err_var_scope = subexpr_scope; - } - else_expr_result = ir_gen_node_extra(irb, else_node, err_var_scope, lval, &peer_parent->peers.at(1)->base); - if (else_expr_result == irb->codegen->invalid_inst_src) - return else_expr_result; - } else { - else_expr_result = ir_build_const_void(irb, scope, node); - ir_build_end_expr(irb, scope, node, else_expr_result, &peer_parent->peers.at(1)->base); - } - IrBasicBlockSrc *after_else_block = irb->current_basic_block; - if (!instr_is_unreachable(else_expr_result)) - ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime)); - - ir_set_cursor_at_end_and_append_block(irb, endif_block); - IrInstSrc **incoming_values = heap::c_allocator.allocate(2); - incoming_values[0] = then_expr_result; - incoming_values[1] = else_expr_result; - IrBasicBlockSrc **incoming_blocks = heap::c_allocator.allocate(2); - incoming_blocks[0] = after_then_block; - incoming_blocks[1] = after_else_block; - - IrInstSrc *phi = ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, peer_parent); - return ir_expr_wrap(irb, scope, phi, result_loc); -} - -static bool ir_gen_switch_prong_expr(IrBuilderSrc *irb, Scope *scope, AstNode *switch_node, AstNode *prong_node, - IrBasicBlockSrc *end_block, IrInstSrc *is_comptime, IrInstSrc *var_is_comptime, - IrInstSrc *target_value_ptr, IrInstSrc **prong_values, size_t prong_values_len, - ZigList *incoming_blocks, ZigList *incoming_values, - IrInstSrcSwitchElseVar **out_switch_else_var, LVal lval, ResultLoc *result_loc) -{ - assert(switch_node->type == NodeTypeSwitchExpr); - assert(prong_node->type == NodeTypeSwitchProng); - - AstNode *expr_node = prong_node->data.switch_prong.expr; - AstNode *var_symbol_node = prong_node->data.switch_prong.var_symbol; - Scope *child_scope; - if (var_symbol_node) { - assert(var_symbol_node->type == NodeTypeSymbol); - Buf *var_name = var_symbol_node->data.symbol_expr.symbol; - bool var_is_ptr = prong_node->data.switch_prong.var_is_ptr; - - bool is_shadowable = false; - bool is_const = true; - ZigVar *var = ir_create_var(irb, var_symbol_node, scope, - var_name, is_const, is_const, is_shadowable, var_is_comptime); - child_scope = var->child_scope; - IrInstSrc *var_value; - if (out_switch_else_var != nullptr) { - IrInstSrcSwitchElseVar *switch_else_var = ir_build_switch_else_var(irb, scope, var_symbol_node, - target_value_ptr); - *out_switch_else_var = switch_else_var; - IrInstSrc *payload_ptr = &switch_else_var->base; - var_value = var_is_ptr ? - payload_ptr : ir_build_load_ptr(irb, scope, var_symbol_node, payload_ptr); - } else if (prong_values != nullptr) { - IrInstSrc *payload_ptr = ir_build_switch_var(irb, scope, var_symbol_node, target_value_ptr, - prong_values, prong_values_len); - var_value = var_is_ptr ? - payload_ptr : ir_build_load_ptr(irb, scope, var_symbol_node, payload_ptr); - } else { - var_value = var_is_ptr ? - target_value_ptr : ir_build_load_ptr(irb, scope, var_symbol_node, target_value_ptr); - } - build_decl_var_and_init(irb, scope, var_symbol_node, var, var_value, buf_ptr(var_name), var_is_comptime); - } else { - child_scope = scope; - } - - IrInstSrc *expr_result = ir_gen_node_extra(irb, expr_node, child_scope, lval, result_loc); - if (expr_result == irb->codegen->invalid_inst_src) - return false; - if (!instr_is_unreachable(expr_result)) - ir_mark_gen(ir_build_br(irb, scope, switch_node, end_block, is_comptime)); - incoming_blocks->append(irb->current_basic_block); - incoming_values->append(expr_result); - return true; -} - -static IrInstSrc *ir_gen_switch_expr(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, - ResultLoc *result_loc) -{ - assert(node->type == NodeTypeSwitchExpr); - - AstNode *target_node = node->data.switch_expr.expr; - IrInstSrc *target_value_ptr = ir_gen_node_extra(irb, target_node, scope, LValPtr, nullptr); - if (target_value_ptr == irb->codegen->invalid_inst_src) - return target_value_ptr; - IrInstSrc *target_value = ir_build_switch_target(irb, scope, node, target_value_ptr); - - IrBasicBlockSrc *else_block = ir_create_basic_block(irb, scope, "SwitchElse"); - IrBasicBlockSrc *end_block = ir_create_basic_block(irb, scope, "SwitchEnd"); - - size_t prong_count = node->data.switch_expr.prongs.length; - ZigList cases = {0}; - - IrInstSrc *is_comptime; - IrInstSrc *var_is_comptime; - if (ir_should_inline(irb->exec, scope)) { - is_comptime = ir_build_const_bool(irb, scope, node, true); - var_is_comptime = is_comptime; - } else { - is_comptime = ir_build_test_comptime(irb, scope, node, target_value); - var_is_comptime = ir_build_test_comptime(irb, scope, node, target_value_ptr); - } - - ZigList incoming_values = {0}; - ZigList incoming_blocks = {0}; - ZigList check_ranges = {0}; - - IrInstSrcSwitchElseVar *switch_else_var = nullptr; - - ResultLocPeerParent *peer_parent = heap::c_allocator.create(); - peer_parent->base.id = ResultLocIdPeerParent; - peer_parent->base.allow_write_through_const = result_loc->allow_write_through_const; - peer_parent->end_bb = end_block; - peer_parent->is_comptime = is_comptime; - peer_parent->parent = result_loc; - - ir_build_reset_result(irb, scope, node, &peer_parent->base); - - // First do the else and the ranges - Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime); - Scope *comptime_scope = create_comptime_scope(irb->codegen, node, scope); - AstNode *else_prong = nullptr; - AstNode *underscore_prong = nullptr; - for (size_t prong_i = 0; prong_i < prong_count; prong_i += 1) { - AstNode *prong_node = node->data.switch_expr.prongs.at(prong_i); - size_t prong_item_count = prong_node->data.switch_prong.items.length; - if (prong_node->data.switch_prong.any_items_are_range) { - ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent); - - IrInstSrc *ok_bit = nullptr; - AstNode *last_item_node = nullptr; - for (size_t item_i = 0; item_i < prong_item_count; item_i += 1) { - AstNode *item_node = prong_node->data.switch_prong.items.at(item_i); - last_item_node = item_node; - if (item_node->type == NodeTypeSwitchRange) { - AstNode *start_node = item_node->data.switch_range.start; - AstNode *end_node = item_node->data.switch_range.end; - - IrInstSrc *start_value = ir_gen_node(irb, start_node, comptime_scope); - if (start_value == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - - IrInstSrc *end_value = ir_gen_node(irb, end_node, comptime_scope); - if (end_value == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - - IrInstSrcCheckSwitchProngsRange *check_range = check_ranges.add_one(); - check_range->start = start_value; - check_range->end = end_value; - - IrInstSrc *lower_range_ok = ir_build_bin_op(irb, scope, item_node, IrBinOpCmpGreaterOrEq, - target_value, start_value, false); - IrInstSrc *upper_range_ok = ir_build_bin_op(irb, scope, item_node, IrBinOpCmpLessOrEq, - target_value, end_value, false); - IrInstSrc *both_ok = ir_build_bin_op(irb, scope, item_node, IrBinOpBoolAnd, - lower_range_ok, upper_range_ok, false); - if (ok_bit) { - ok_bit = ir_build_bin_op(irb, scope, item_node, IrBinOpBoolOr, both_ok, ok_bit, false); - } else { - ok_bit = both_ok; - } - } else { - IrInstSrc *item_value = ir_gen_node(irb, item_node, comptime_scope); - if (item_value == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - - IrInstSrcCheckSwitchProngsRange *check_range = check_ranges.add_one(); - check_range->start = item_value; - check_range->end = item_value; - - IrInstSrc *cmp_ok = ir_build_bin_op(irb, scope, item_node, IrBinOpCmpEq, - item_value, target_value, false); - if (ok_bit) { - ok_bit = ir_build_bin_op(irb, scope, item_node, IrBinOpBoolOr, cmp_ok, ok_bit, false); - } else { - ok_bit = cmp_ok; - } - } - } - - IrBasicBlockSrc *range_block_yes = ir_create_basic_block(irb, scope, "SwitchRangeYes"); - IrBasicBlockSrc *range_block_no = ir_create_basic_block(irb, scope, "SwitchRangeNo"); - - assert(ok_bit); - assert(last_item_node); - IrInstSrc *br_inst = ir_mark_gen(ir_build_cond_br(irb, scope, last_item_node, ok_bit, - range_block_yes, range_block_no, is_comptime)); - if (peer_parent->base.source_instruction == nullptr) { - peer_parent->base.source_instruction = br_inst; - } - - if (peer_parent->peers.length > 0) { - peer_parent->peers.last()->next_bb = range_block_yes; - } - peer_parent->peers.append(this_peer_result_loc); - ir_set_cursor_at_end_and_append_block(irb, range_block_yes); - if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block, - is_comptime, var_is_comptime, target_value_ptr, nullptr, 0, - &incoming_blocks, &incoming_values, nullptr, LValNone, &this_peer_result_loc->base)) - { - return irb->codegen->invalid_inst_src; - } - - ir_set_cursor_at_end_and_append_block(irb, range_block_no); - } else { - if (prong_item_count == 0) { - if (else_prong) { - ErrorMsg *msg = add_node_error(irb->codegen, prong_node, - buf_sprintf("multiple else prongs in switch expression")); - add_error_note(irb->codegen, msg, else_prong, - buf_sprintf("previous else prong is here")); - return irb->codegen->invalid_inst_src; - } - else_prong = prong_node; - } else if (prong_item_count == 1 && - prong_node->data.switch_prong.items.at(0)->type == NodeTypeSymbol && - buf_eql_str(prong_node->data.switch_prong.items.at(0)->data.symbol_expr.symbol, "_")) { - if (underscore_prong) { - ErrorMsg *msg = add_node_error(irb->codegen, prong_node, - buf_sprintf("multiple '_' prongs in switch expression")); - add_error_note(irb->codegen, msg, underscore_prong, - buf_sprintf("previous '_' prong is here")); - return irb->codegen->invalid_inst_src; - } - underscore_prong = prong_node; - } else { - continue; - } - if (underscore_prong && else_prong) { - ErrorMsg *msg = add_node_error(irb->codegen, prong_node, - buf_sprintf("else and '_' prong in switch expression")); - if (underscore_prong == prong_node) - add_error_note(irb->codegen, msg, else_prong, - buf_sprintf("else prong is here")); - else - add_error_note(irb->codegen, msg, underscore_prong, - buf_sprintf("'_' prong is here")); - return irb->codegen->invalid_inst_src; - } - ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent); - - IrBasicBlockSrc *prev_block = irb->current_basic_block; - if (peer_parent->peers.length > 0) { - peer_parent->peers.last()->next_bb = else_block; - } - peer_parent->peers.append(this_peer_result_loc); - ir_set_cursor_at_end_and_append_block(irb, else_block); - if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block, - is_comptime, var_is_comptime, target_value_ptr, nullptr, 0, &incoming_blocks, &incoming_values, - &switch_else_var, LValNone, &this_peer_result_loc->base)) - { - return irb->codegen->invalid_inst_src; - } - ir_set_cursor_at_end(irb, prev_block); - } - } - - // next do the non-else non-ranges - for (size_t prong_i = 0; prong_i < prong_count; prong_i += 1) { - AstNode *prong_node = node->data.switch_expr.prongs.at(prong_i); - size_t prong_item_count = prong_node->data.switch_prong.items.length; - if (prong_item_count == 0) - continue; - if (prong_node->data.switch_prong.any_items_are_range) - continue; - if (underscore_prong == prong_node) - continue; - - ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent); - - IrBasicBlockSrc *prong_block = ir_create_basic_block(irb, scope, "SwitchProng"); - IrInstSrc **items = heap::c_allocator.allocate(prong_item_count); - - for (size_t item_i = 0; item_i < prong_item_count; item_i += 1) { - AstNode *item_node = prong_node->data.switch_prong.items.at(item_i); - assert(item_node->type != NodeTypeSwitchRange); - - IrInstSrc *item_value = ir_gen_node(irb, item_node, comptime_scope); - if (item_value == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - - IrInstSrcCheckSwitchProngsRange *check_range = check_ranges.add_one(); - check_range->start = item_value; - check_range->end = item_value; - - IrInstSrcSwitchBrCase *this_case = cases.add_one(); - this_case->value = item_value; - this_case->block = prong_block; - - items[item_i] = item_value; - } - - IrBasicBlockSrc *prev_block = irb->current_basic_block; - if (peer_parent->peers.length > 0) { - peer_parent->peers.last()->next_bb = prong_block; - } - peer_parent->peers.append(this_peer_result_loc); - ir_set_cursor_at_end_and_append_block(irb, prong_block); - if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block, - is_comptime, var_is_comptime, target_value_ptr, items, prong_item_count, - &incoming_blocks, &incoming_values, nullptr, LValNone, &this_peer_result_loc->base)) - { - return irb->codegen->invalid_inst_src; - } - - ir_set_cursor_at_end(irb, prev_block); - - } - - IrInstSrc *switch_prongs_void = ir_build_check_switch_prongs(irb, scope, node, target_value, - check_ranges.items, check_ranges.length, else_prong, underscore_prong != nullptr); - - IrInstSrc *br_instruction; - if (cases.length == 0) { - br_instruction = ir_build_br(irb, scope, node, else_block, is_comptime); - } else { - IrInstSrcSwitchBr *switch_br = ir_build_switch_br_src(irb, scope, node, target_value, else_block, - cases.length, cases.items, is_comptime, switch_prongs_void); - if (switch_else_var != nullptr) { - switch_else_var->switch_br = switch_br; - } - br_instruction = &switch_br->base; - } - if (peer_parent->base.source_instruction == nullptr) { - peer_parent->base.source_instruction = br_instruction; - } - for (size_t i = 0; i < peer_parent->peers.length; i += 1) { - peer_parent->peers.at(i)->base.source_instruction = peer_parent->base.source_instruction; - } - - if (!else_prong && !underscore_prong) { - if (peer_parent->peers.length != 0) { - peer_parent->peers.last()->next_bb = else_block; - } - ir_set_cursor_at_end_and_append_block(irb, else_block); - ir_build_unreachable(irb, scope, node); - } else { - if (peer_parent->peers.length != 0) { - peer_parent->peers.last()->next_bb = end_block; - } - } - - ir_set_cursor_at_end_and_append_block(irb, end_block); - assert(incoming_blocks.length == incoming_values.length); - IrInstSrc *result_instruction; - if (incoming_blocks.length == 0) { - result_instruction = ir_build_const_void(irb, scope, node); - } else { - result_instruction = ir_build_phi(irb, scope, node, incoming_blocks.length, - incoming_blocks.items, incoming_values.items, peer_parent); - } - return ir_lval_wrap(irb, scope, result_instruction, lval, result_loc); -} - -static IrInstSrc *ir_gen_comptime(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node, LVal lval) { - assert(node->type == NodeTypeCompTime); - - Scope *child_scope = create_comptime_scope(irb->codegen, node, parent_scope); - // purposefully pass null for result_loc and let EndExpr handle it - return ir_gen_node_extra(irb, node->data.comptime_expr.expr, child_scope, lval, nullptr); -} - -static IrInstSrc *ir_gen_nosuspend(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node, LVal lval) { - assert(node->type == NodeTypeNoSuspend); - - Scope *child_scope = create_nosuspend_scope(irb->codegen, node, parent_scope); - // purposefully pass null for result_loc and let EndExpr handle it - return ir_gen_node_extra(irb, node->data.nosuspend_expr.expr, child_scope, lval, nullptr); -} - -static IrInstSrc *ir_gen_return_from_block(IrBuilderSrc *irb, Scope *break_scope, AstNode *node, ScopeBlock *block_scope) { - IrInstSrc *is_comptime; - if (ir_should_inline(irb->exec, break_scope)) { - is_comptime = ir_build_const_bool(irb, break_scope, node, true); - } else { - is_comptime = block_scope->is_comptime; - } - - IrInstSrc *result_value; - if (node->data.break_expr.expr) { - ResultLocPeer *peer_result = create_peer_result(block_scope->peer_parent); - block_scope->peer_parent->peers.append(peer_result); - - result_value = ir_gen_node_extra(irb, node->data.break_expr.expr, break_scope, block_scope->lval, - &peer_result->base); - if (result_value == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - } else { - result_value = ir_build_const_void(irb, break_scope, node); - } - - IrBasicBlockSrc *dest_block = block_scope->end_block; - if (!ir_gen_defers_for_block(irb, break_scope, dest_block->scope, nullptr, nullptr)) - return irb->codegen->invalid_inst_src; - - block_scope->incoming_blocks->append(irb->current_basic_block); - block_scope->incoming_values->append(result_value); - return ir_build_br(irb, break_scope, node, dest_block, is_comptime); -} - -static IrInstSrc *ir_gen_break(IrBuilderSrc *irb, Scope *break_scope, AstNode *node) { - assert(node->type == NodeTypeBreak); - - // Search up the scope. We'll find one of these things first: - // * function definition scope or global scope => error, break outside loop - // * defer expression scope => error, cannot break out of defer expression - // * loop scope => OK - // * (if it's a labeled break) labeled block => OK - - Scope *search_scope = break_scope; - ScopeLoop *loop_scope; - for (;;) { - if (search_scope == nullptr || search_scope->id == ScopeIdFnDef) { - if (node->data.break_expr.name != nullptr) { - add_node_error(irb->codegen, node, buf_sprintf("label not found: '%s'", buf_ptr(node->data.break_expr.name))); - return irb->codegen->invalid_inst_src; - } else { - add_node_error(irb->codegen, node, buf_sprintf("break expression outside loop")); - return irb->codegen->invalid_inst_src; - } - } else if (search_scope->id == ScopeIdDeferExpr) { - add_node_error(irb->codegen, node, buf_sprintf("cannot break out of defer expression")); - return irb->codegen->invalid_inst_src; - } else if (search_scope->id == ScopeIdLoop) { - ScopeLoop *this_loop_scope = (ScopeLoop *)search_scope; - if (node->data.break_expr.name == nullptr || - (this_loop_scope->name != nullptr && buf_eql_buf(node->data.break_expr.name, this_loop_scope->name))) - { - this_loop_scope->name_used = true; - loop_scope = this_loop_scope; - break; - } - } else if (search_scope->id == ScopeIdBlock) { - ScopeBlock *this_block_scope = (ScopeBlock *)search_scope; - if (node->data.break_expr.name != nullptr && - (this_block_scope->name != nullptr && buf_eql_buf(node->data.break_expr.name, this_block_scope->name))) - { - assert(this_block_scope->end_block != nullptr); - this_block_scope->name_used = true; - return ir_gen_return_from_block(irb, break_scope, node, this_block_scope); - } - } else if (search_scope->id == ScopeIdSuspend) { - add_node_error(irb->codegen, node, buf_sprintf("cannot break out of suspend block")); - return irb->codegen->invalid_inst_src; - } - search_scope = search_scope->parent; - } - - IrInstSrc *is_comptime; - if (ir_should_inline(irb->exec, break_scope)) { - is_comptime = ir_build_const_bool(irb, break_scope, node, true); - } else { - is_comptime = loop_scope->is_comptime; - } - - IrInstSrc *result_value; - if (node->data.break_expr.expr) { - ResultLocPeer *peer_result = create_peer_result(loop_scope->peer_parent); - loop_scope->peer_parent->peers.append(peer_result); - - result_value = ir_gen_node_extra(irb, node->data.break_expr.expr, break_scope, - loop_scope->lval, &peer_result->base); - if (result_value == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - } else { - result_value = ir_build_const_void(irb, break_scope, node); - } - - IrBasicBlockSrc *dest_block = loop_scope->break_block; - if (!ir_gen_defers_for_block(irb, break_scope, dest_block->scope, nullptr, nullptr)) - return irb->codegen->invalid_inst_src; - - loop_scope->incoming_blocks->append(irb->current_basic_block); - loop_scope->incoming_values->append(result_value); - return ir_build_br(irb, break_scope, node, dest_block, is_comptime); -} - -static IrInstSrc *ir_gen_continue(IrBuilderSrc *irb, Scope *continue_scope, AstNode *node) { - assert(node->type == NodeTypeContinue); - - // Search up the scope. We'll find one of these things first: - // * function definition scope or global scope => error, break outside loop - // * defer expression scope => error, cannot break out of defer expression - // * loop scope => OK - - ZigList runtime_scopes = {}; - - Scope *search_scope = continue_scope; - ScopeLoop *loop_scope; - for (;;) { - if (search_scope == nullptr || search_scope->id == ScopeIdFnDef) { - if (node->data.continue_expr.name != nullptr) { - add_node_error(irb->codegen, node, buf_sprintf("labeled loop not found: '%s'", buf_ptr(node->data.continue_expr.name))); - return irb->codegen->invalid_inst_src; - } else { - add_node_error(irb->codegen, node, buf_sprintf("continue expression outside loop")); - return irb->codegen->invalid_inst_src; - } - } else if (search_scope->id == ScopeIdDeferExpr) { - add_node_error(irb->codegen, node, buf_sprintf("cannot continue out of defer expression")); - return irb->codegen->invalid_inst_src; - } else if (search_scope->id == ScopeIdLoop) { - ScopeLoop *this_loop_scope = (ScopeLoop *)search_scope; - if (node->data.continue_expr.name == nullptr || - (this_loop_scope->name != nullptr && buf_eql_buf(node->data.continue_expr.name, this_loop_scope->name))) - { - this_loop_scope->name_used = true; - loop_scope = this_loop_scope; - break; - } - } else if (search_scope->id == ScopeIdRuntime) { - ScopeRuntime *scope_runtime = (ScopeRuntime *)search_scope; - runtime_scopes.append(scope_runtime); - } - search_scope = search_scope->parent; - } - - IrInstSrc *is_comptime; - if (ir_should_inline(irb->exec, continue_scope)) { - is_comptime = ir_build_const_bool(irb, continue_scope, node, true); - } else { - is_comptime = loop_scope->is_comptime; - } - - for (size_t i = 0; i < runtime_scopes.length; i += 1) { - ScopeRuntime *scope_runtime = runtime_scopes.at(i); - ir_mark_gen(ir_build_check_runtime_scope(irb, continue_scope, node, scope_runtime->is_comptime, is_comptime)); - } - runtime_scopes.deinit(); - - IrBasicBlockSrc *dest_block = loop_scope->continue_block; - if (!ir_gen_defers_for_block(irb, continue_scope, dest_block->scope, nullptr, nullptr)) - return irb->codegen->invalid_inst_src; - return ir_mark_gen(ir_build_br(irb, continue_scope, node, dest_block, is_comptime)); -} - -static IrInstSrc *ir_gen_error_type(IrBuilderSrc *irb, Scope *scope, AstNode *node) { - assert(node->type == NodeTypeErrorType); - return ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_global_error_set); -} - -static IrInstSrc *ir_gen_defer(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node) { - assert(node->type == NodeTypeDefer); - - ScopeDefer *defer_child_scope = create_defer_scope(irb->codegen, node, parent_scope); - node->data.defer.child_scope = &defer_child_scope->base; - - ScopeDeferExpr *defer_expr_scope = create_defer_expr_scope(irb->codegen, node, parent_scope); - node->data.defer.expr_scope = &defer_expr_scope->base; - - return ir_build_const_void(irb, parent_scope, node); -} - -static IrInstSrc *ir_gen_slice(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { - assert(node->type == NodeTypeSliceExpr); - - AstNodeSliceExpr *slice_expr = &node->data.slice_expr; - AstNode *array_node = slice_expr->array_ref_expr; - AstNode *start_node = slice_expr->start; - AstNode *end_node = slice_expr->end; - AstNode *sentinel_node = slice_expr->sentinel; - - IrInstSrc *ptr_value = ir_gen_node_extra(irb, array_node, scope, LValPtr, nullptr); - if (ptr_value == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - - IrInstSrc *start_value = ir_gen_node(irb, start_node, scope); - if (start_value == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - - IrInstSrc *end_value; - if (end_node) { - end_value = ir_gen_node(irb, end_node, scope); - if (end_value == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - } else { - end_value = nullptr; - } - - IrInstSrc *sentinel_value; - if (sentinel_node) { - sentinel_value = ir_gen_node(irb, sentinel_node, scope); - if (sentinel_value == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - } else { - sentinel_value = nullptr; - } - - IrInstSrc *slice = ir_build_slice_src(irb, scope, node, ptr_value, start_value, end_value, - sentinel_value, true, result_loc); - return ir_lval_wrap(irb, scope, slice, lval, result_loc); -} - -static IrInstSrc *ir_gen_catch(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node, LVal lval, - ResultLoc *result_loc) -{ - assert(node->type == NodeTypeCatchExpr); - - AstNode *op1_node = node->data.unwrap_err_expr.op1; - AstNode *op2_node = node->data.unwrap_err_expr.op2; - AstNode *var_node = node->data.unwrap_err_expr.symbol; - - if (op2_node->type == NodeTypeUnreachable) { - if (var_node != nullptr) { - assert(var_node->type == NodeTypeSymbol); - Buf *var_name = var_node->data.symbol_expr.symbol; - add_node_error(irb->codegen, var_node, buf_sprintf("unused variable: '%s'", buf_ptr(var_name))); - return irb->codegen->invalid_inst_src; - } - return ir_gen_catch_unreachable(irb, parent_scope, node, op1_node, lval, result_loc); - } - - - ScopeExpr *spill_scope = create_expr_scope(irb->codegen, op1_node, parent_scope); - spill_scope->spill_harder = true; - - IrInstSrc *err_union_ptr = ir_gen_node_extra(irb, op1_node, &spill_scope->base, LValPtr, nullptr); - if (err_union_ptr == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - - IrInstSrc *is_err = ir_build_test_err_src(irb, parent_scope, node, err_union_ptr, true, false); - - IrInstSrc *is_comptime; - if (ir_should_inline(irb->exec, parent_scope)) { - is_comptime = ir_build_const_bool(irb, parent_scope, node, true); - } else { - is_comptime = ir_build_test_comptime(irb, parent_scope, node, is_err); - } - - IrBasicBlockSrc *ok_block = ir_create_basic_block(irb, parent_scope, "UnwrapErrOk"); - IrBasicBlockSrc *err_block = ir_create_basic_block(irb, parent_scope, "UnwrapErrError"); - IrBasicBlockSrc *end_block = ir_create_basic_block(irb, parent_scope, "UnwrapErrEnd"); - IrInstSrc *cond_br_inst = ir_build_cond_br(irb, parent_scope, node, is_err, err_block, ok_block, is_comptime); - - ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, ok_block, end_block, result_loc, - is_comptime); - - ir_set_cursor_at_end_and_append_block(irb, err_block); - Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, &spill_scope->base, is_comptime); - Scope *err_scope; - if (var_node) { - assert(var_node->type == NodeTypeSymbol); - Buf *var_name = var_node->data.symbol_expr.symbol; - bool is_const = true; - bool is_shadowable = false; - ZigVar *var = ir_create_var(irb, node, subexpr_scope, var_name, - is_const, is_const, is_shadowable, is_comptime); - err_scope = var->child_scope; - IrInstSrc *err_ptr = ir_build_unwrap_err_code_src(irb, err_scope, node, err_union_ptr); - IrInstSrc *err_value = ir_build_load_ptr(irb, err_scope, var_node, err_ptr); - build_decl_var_and_init(irb, err_scope, var_node, var, err_value, buf_ptr(var_name), is_comptime); - } else { - err_scope = subexpr_scope; - } - IrInstSrc *err_result = ir_gen_node_extra(irb, op2_node, err_scope, LValNone, &peer_parent->peers.at(0)->base); - if (err_result == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - IrBasicBlockSrc *after_err_block = irb->current_basic_block; - if (!instr_is_unreachable(err_result)) - ir_mark_gen(ir_build_br(irb, parent_scope, node, end_block, is_comptime)); - - ir_set_cursor_at_end_and_append_block(irb, ok_block); - IrInstSrc *unwrapped_ptr = ir_build_unwrap_err_payload_src(irb, parent_scope, node, err_union_ptr, false, false); - IrInstSrc *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr); - ir_build_end_expr(irb, parent_scope, node, unwrapped_payload, &peer_parent->peers.at(1)->base); - IrBasicBlockSrc *after_ok_block = irb->current_basic_block; - ir_build_br(irb, parent_scope, node, end_block, is_comptime); - - ir_set_cursor_at_end_and_append_block(irb, end_block); - IrInstSrc **incoming_values = heap::c_allocator.allocate(2); - incoming_values[0] = err_result; - incoming_values[1] = unwrapped_payload; - IrBasicBlockSrc **incoming_blocks = heap::c_allocator.allocate(2); - incoming_blocks[0] = after_err_block; - incoming_blocks[1] = after_ok_block; - IrInstSrc *phi = ir_build_phi(irb, parent_scope, node, 2, incoming_blocks, incoming_values, peer_parent); - return ir_lval_wrap(irb, parent_scope, phi, lval, result_loc); -} - -static bool render_instance_name_recursive(CodeGen *codegen, Buf *name, Scope *outer_scope, Scope *inner_scope) { - if (inner_scope == nullptr || inner_scope == outer_scope) return false; - bool need_comma = render_instance_name_recursive(codegen, name, outer_scope, inner_scope->parent); - if (inner_scope->id != ScopeIdVarDecl) - return need_comma; - - ScopeVarDecl *var_scope = (ScopeVarDecl *)inner_scope; - if (need_comma) - buf_append_char(name, ','); - // TODO: const ptr reinterpret here to make the var type agree with the value? - render_const_value(codegen, name, var_scope->var->const_value); - return true; -} - -static Buf *get_anon_type_name(CodeGen *codegen, IrExecutableSrc *exec, const char *kind_name, - Scope *scope, AstNode *source_node, Buf *out_bare_name) -{ - if (exec != nullptr && exec->name) { - ZigType *import = get_scope_import(scope); - Buf *namespace_name = buf_alloc(); - append_namespace_qualification(codegen, namespace_name, import); - buf_append_buf(namespace_name, exec->name); - buf_init_from_buf(out_bare_name, exec->name); - return namespace_name; - } else if (exec != nullptr && exec->name_fn != nullptr) { - Buf *name = buf_alloc(); - buf_append_buf(name, &exec->name_fn->symbol_name); - buf_appendf(name, "("); - render_instance_name_recursive(codegen, name, &exec->name_fn->fndef_scope->base, exec->begin_scope); - buf_appendf(name, ")"); - buf_init_from_buf(out_bare_name, name); - return name; - } else { - ZigType *import = get_scope_import(scope); - Buf *namespace_name = buf_alloc(); - append_namespace_qualification(codegen, namespace_name, import); - buf_appendf(namespace_name, "%s:%" ZIG_PRI_usize ":%" ZIG_PRI_usize, kind_name, - source_node->line + 1, source_node->column + 1); - buf_init_from_buf(out_bare_name, namespace_name); - return namespace_name; - } -} - -static IrInstSrc *ir_gen_container_decl(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node) { - assert(node->type == NodeTypeContainerDecl); - - ContainerKind kind = node->data.container_decl.kind; - Buf *bare_name = buf_alloc(); - Buf *name = get_anon_type_name(irb->codegen, irb->exec, container_string(kind), parent_scope, node, bare_name); - - ContainerLayout layout = node->data.container_decl.layout; - ZigType *container_type = get_partial_container_type(irb->codegen, parent_scope, - kind, node, buf_ptr(name), bare_name, layout); - ScopeDecls *child_scope = get_container_scope(container_type); - - for (size_t i = 0; i < node->data.container_decl.decls.length; i += 1) { - AstNode *child_node = node->data.container_decl.decls.at(i); - scan_decls(irb->codegen, child_scope, child_node); - } - - TldContainer *tld_container = heap::c_allocator.create(); - init_tld(&tld_container->base, TldIdContainer, bare_name, VisibModPub, node, parent_scope); - tld_container->type_entry = container_type; - tld_container->decls_scope = child_scope; - irb->codegen->resolve_queue.append(&tld_container->base); - - // Add this to the list to mark as invalid if analyzing this exec fails. - irb->exec->tld_list.append(&tld_container->base); - - return ir_build_const_type(irb, parent_scope, node, container_type); -} - // errors should be populated with set1's values static ZigType *get_error_set_union(CodeGen *g, ErrorTableEntry **errors, ZigType *set1, ZigType *set2, Buf *type_name) @@ -10003,497 +2511,6 @@ static ZigType *make_err_set_with_one_item(CodeGen *g, Scope *parent_scope, AstN return err_set_type; } -static AstNode *ast_field_to_symbol_node(AstNode *err_set_field_node) { - if (err_set_field_node->type == NodeTypeSymbol) { - return err_set_field_node; - } else if (err_set_field_node->type == NodeTypeErrorSetField) { - assert(err_set_field_node->data.err_set_field.field_name->type == NodeTypeSymbol); - return err_set_field_node->data.err_set_field.field_name; - } else { - return err_set_field_node; - } -} - -static IrInstSrc *ir_gen_err_set_decl(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node) { - assert(node->type == NodeTypeErrorSetDecl); - - uint32_t err_count = node->data.err_set_decl.decls.length; - - Buf bare_name = BUF_INIT; - Buf *type_name = get_anon_type_name(irb->codegen, irb->exec, "error", parent_scope, node, &bare_name); - ZigType *err_set_type = new_type_table_entry(ZigTypeIdErrorSet); - buf_init_from_buf(&err_set_type->name, type_name); - err_set_type->data.error_set.err_count = err_count; - err_set_type->size_in_bits = irb->codegen->builtin_types.entry_global_error_set->size_in_bits; - err_set_type->abi_align = irb->codegen->builtin_types.entry_global_error_set->abi_align; - err_set_type->abi_size = irb->codegen->builtin_types.entry_global_error_set->abi_size; - err_set_type->data.error_set.errors = heap::c_allocator.allocate(err_count); - - size_t errors_count = irb->codegen->errors_by_index.length + err_count; - ErrorTableEntry **errors = heap::c_allocator.allocate(errors_count); - - for (uint32_t i = 0; i < err_count; i += 1) { - AstNode *field_node = node->data.err_set_decl.decls.at(i); - AstNode *symbol_node = ast_field_to_symbol_node(field_node); - Buf *err_name = symbol_node->data.symbol_expr.symbol; - ErrorTableEntry *err = heap::c_allocator.create(); - err->decl_node = field_node; - buf_init_from_buf(&err->name, err_name); - - auto existing_entry = irb->codegen->error_table.put_unique(err_name, err); - if (existing_entry) { - err->value = existing_entry->value->value; - } else { - size_t error_value_count = irb->codegen->errors_by_index.length; - assert((uint32_t)error_value_count < (((uint32_t)1) << (uint32_t)irb->codegen->err_tag_type->data.integral.bit_count)); - err->value = error_value_count; - irb->codegen->errors_by_index.append(err); - } - err_set_type->data.error_set.errors[i] = err; - - ErrorTableEntry *prev_err = errors[err->value]; - if (prev_err != nullptr) { - ErrorMsg *msg = add_node_error(irb->codegen, ast_field_to_symbol_node(err->decl_node), - buf_sprintf("duplicate error: '%s'", buf_ptr(&err->name))); - add_error_note(irb->codegen, msg, ast_field_to_symbol_node(prev_err->decl_node), - buf_sprintf("other error here")); - return irb->codegen->invalid_inst_src; - } - errors[err->value] = err; - } - heap::c_allocator.deallocate(errors, errors_count); - return ir_build_const_type(irb, parent_scope, node, err_set_type); -} - -static IrInstSrc *ir_gen_fn_proto(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node) { - assert(node->type == NodeTypeFnProto); - - size_t param_count = node->data.fn_proto.params.length; - IrInstSrc **param_types = heap::c_allocator.allocate(param_count); - - bool is_var_args = false; - for (size_t i = 0; i < param_count; i += 1) { - AstNode *param_node = node->data.fn_proto.params.at(i); - if (param_node->data.param_decl.is_var_args) { - is_var_args = true; - break; - } - if (param_node->data.param_decl.anytype_token == nullptr) { - AstNode *type_node = param_node->data.param_decl.type; - IrInstSrc *type_value = ir_gen_node(irb, type_node, parent_scope); - if (type_value == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - param_types[i] = type_value; - } else { - param_types[i] = nullptr; - } - } - - IrInstSrc *align_value = nullptr; - if (node->data.fn_proto.align_expr != nullptr) { - align_value = ir_gen_node(irb, node->data.fn_proto.align_expr, parent_scope); - if (align_value == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - } - - IrInstSrc *callconv_value = nullptr; - if (node->data.fn_proto.callconv_expr != nullptr) { - callconv_value = ir_gen_node(irb, node->data.fn_proto.callconv_expr, parent_scope); - if (callconv_value == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - } - - IrInstSrc *return_type; - if (node->data.fn_proto.return_type == nullptr) { - return_type = ir_build_const_type(irb, parent_scope, node, irb->codegen->builtin_types.entry_void); - } else { - return_type = ir_gen_node(irb, node->data.fn_proto.return_type, parent_scope); - if (return_type == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - } - - return ir_build_fn_proto(irb, parent_scope, node, param_types, align_value, callconv_value, return_type, is_var_args); -} - -static IrInstSrc *ir_gen_resume(IrBuilderSrc *irb, Scope *scope, AstNode *node) { - assert(node->type == NodeTypeResume); - - IrInstSrc *target_inst = ir_gen_node_extra(irb, node->data.resume_expr.expr, scope, LValPtr, nullptr); - if (target_inst == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - - return ir_build_resume_src(irb, scope, node, target_inst); -} - -static IrInstSrc *ir_gen_await_expr(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, - ResultLoc *result_loc) -{ - assert(node->type == NodeTypeAwaitExpr); - - bool is_nosuspend = get_scope_nosuspend(scope) != nullptr; - - AstNode *expr_node = node->data.await_expr.expr; - if (expr_node->type == NodeTypeFnCallExpr && expr_node->data.fn_call_expr.modifier == CallModifierBuiltin) { - AstNode *fn_ref_expr = expr_node->data.fn_call_expr.fn_ref_expr; - Buf *name = fn_ref_expr->data.symbol_expr.symbol; - auto entry = irb->codegen->builtin_fn_table.maybe_get(name); - if (entry != nullptr) { - BuiltinFnEntry *builtin_fn = entry->value; - if (builtin_fn->id == BuiltinFnIdAsyncCall) { - return ir_gen_async_call(irb, scope, node, expr_node, lval, result_loc); - } - } - } - - ZigFn *fn_entry = exec_fn_entry(irb->exec); - if (!fn_entry) { - add_node_error(irb->codegen, node, buf_sprintf("await outside function definition")); - return irb->codegen->invalid_inst_src; - } - ScopeSuspend *existing_suspend_scope = get_scope_suspend(scope); - if (existing_suspend_scope) { - if (!existing_suspend_scope->reported_err) { - ErrorMsg *msg = add_node_error(irb->codegen, node, buf_sprintf("cannot await inside suspend block")); - add_error_note(irb->codegen, msg, existing_suspend_scope->base.source_node, buf_sprintf("suspend block here")); - existing_suspend_scope->reported_err = true; - } - return irb->codegen->invalid_inst_src; - } - - IrInstSrc *target_inst = ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr); - if (target_inst == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - - IrInstSrc *await_inst = ir_build_await_src(irb, scope, node, target_inst, result_loc, is_nosuspend); - return ir_lval_wrap(irb, scope, await_inst, lval, result_loc); -} - -static IrInstSrc *ir_gen_suspend(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node) { - assert(node->type == NodeTypeSuspend); - - ZigFn *fn_entry = exec_fn_entry(irb->exec); - if (!fn_entry) { - add_node_error(irb->codegen, node, buf_sprintf("suspend outside function definition")); - return irb->codegen->invalid_inst_src; - } - if (get_scope_nosuspend(parent_scope) != nullptr) { - add_node_error(irb->codegen, node, buf_sprintf("suspend in nosuspend scope")); - return irb->codegen->invalid_inst_src; - } - - ScopeSuspend *existing_suspend_scope = get_scope_suspend(parent_scope); - if (existing_suspend_scope) { - if (!existing_suspend_scope->reported_err) { - ErrorMsg *msg = add_node_error(irb->codegen, node, buf_sprintf("cannot suspend inside suspend block")); - add_error_note(irb->codegen, msg, existing_suspend_scope->base.source_node, buf_sprintf("other suspend block here")); - existing_suspend_scope->reported_err = true; - } - return irb->codegen->invalid_inst_src; - } - - IrInstSrcSuspendBegin *begin = ir_build_suspend_begin_src(irb, parent_scope, node); - ScopeSuspend *suspend_scope = create_suspend_scope(irb->codegen, node, parent_scope); - Scope *child_scope = &suspend_scope->base; - IrInstSrc *susp_res = ir_gen_node(irb, node->data.suspend.block, child_scope); - if (susp_res == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - ir_mark_gen(ir_build_check_statement_is_void(irb, child_scope, node->data.suspend.block, susp_res)); - - return ir_mark_gen(ir_build_suspend_finish_src(irb, parent_scope, node, begin)); -} - -static IrInstSrc *ir_gen_node_raw(IrBuilderSrc *irb, AstNode *node, Scope *scope, - LVal lval, ResultLoc *result_loc) -{ - assert(scope); - switch (node->type) { - case NodeTypeStructValueField: - case NodeTypeParamDecl: - case NodeTypeUsingNamespace: - case NodeTypeSwitchProng: - case NodeTypeSwitchRange: - case NodeTypeStructField: - case NodeTypeErrorSetField: - case NodeTypeFnDef: - case NodeTypeTestDecl: - zig_unreachable(); - case NodeTypeBlock: - return ir_gen_block(irb, scope, node, lval, result_loc); - case NodeTypeGroupedExpr: - return ir_gen_node_raw(irb, node->data.grouped_expr, scope, lval, result_loc); - case NodeTypeBinOpExpr: - return ir_gen_bin_op(irb, scope, node, lval, result_loc); - case NodeTypeIntLiteral: - return ir_lval_wrap(irb, scope, ir_gen_int_lit(irb, scope, node), lval, result_loc); - case NodeTypeFloatLiteral: - return ir_lval_wrap(irb, scope, ir_gen_float_lit(irb, scope, node), lval, result_loc); - case NodeTypeCharLiteral: - return ir_lval_wrap(irb, scope, ir_gen_char_lit(irb, scope, node), lval, result_loc); - case NodeTypeSymbol: - return ir_gen_symbol(irb, scope, node, lval, result_loc); - case NodeTypeFnCallExpr: - return ir_gen_fn_call(irb, scope, node, lval, result_loc); - case NodeTypeIfBoolExpr: - return ir_gen_if_bool_expr(irb, scope, node, lval, result_loc); - case NodeTypePrefixOpExpr: - return ir_gen_prefix_op_expr(irb, scope, node, lval, result_loc); - case NodeTypeContainerInitExpr: - return ir_gen_container_init_expr(irb, scope, node, lval, result_loc); - case NodeTypeVariableDeclaration: - return ir_gen_var_decl(irb, scope, node); - case NodeTypeWhileExpr: - return ir_gen_while_expr(irb, scope, node, lval, result_loc); - case NodeTypeForExpr: - return ir_gen_for_expr(irb, scope, node, lval, result_loc); - case NodeTypeArrayAccessExpr: - return ir_gen_array_access(irb, scope, node, lval, result_loc); - case NodeTypeReturnExpr: - return ir_gen_return(irb, scope, node, lval, result_loc); - case NodeTypeFieldAccessExpr: - { - IrInstSrc *ptr_instruction = ir_gen_field_access(irb, scope, node); - if (ptr_instruction == irb->codegen->invalid_inst_src) - return ptr_instruction; - if (lval == LValPtr || lval == LValAssign) - return ptr_instruction; - - IrInstSrc *load_ptr = ir_build_load_ptr(irb, scope, node, ptr_instruction); - return ir_expr_wrap(irb, scope, load_ptr, result_loc); - } - case NodeTypePtrDeref: { - AstNode *expr_node = node->data.ptr_deref_expr.target; - - LVal child_lval = lval; - if (child_lval == LValAssign) - child_lval = LValPtr; - - IrInstSrc *value = ir_gen_node_extra(irb, expr_node, scope, child_lval, nullptr); - if (value == irb->codegen->invalid_inst_src) - return value; - - // We essentially just converted any lvalue from &(x.*) to (&x).*; - // this inhibits checking that x is a pointer later, so we directly - // record whether the pointer check is needed - IrInstSrc *un_op = ir_build_un_op_lval(irb, scope, node, IrUnOpDereference, value, lval, result_loc); - return ir_expr_wrap(irb, scope, un_op, result_loc); - } - case NodeTypeUnwrapOptional: { - AstNode *expr_node = node->data.unwrap_optional.expr; - - IrInstSrc *maybe_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr); - if (maybe_ptr == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - - IrInstSrc *unwrapped_ptr = ir_build_optional_unwrap_ptr(irb, scope, node, maybe_ptr, true ); - if (lval == LValPtr || lval == LValAssign) - return unwrapped_ptr; - - IrInstSrc *load_ptr = ir_build_load_ptr(irb, scope, node, unwrapped_ptr); - return ir_expr_wrap(irb, scope, load_ptr, result_loc); - } - case NodeTypeBoolLiteral: - return ir_lval_wrap(irb, scope, ir_gen_bool_literal(irb, scope, node), lval, result_loc); - case NodeTypeArrayType: - return ir_lval_wrap(irb, scope, ir_gen_array_type(irb, scope, node), lval, result_loc); - case NodeTypePointerType: - return ir_lval_wrap(irb, scope, ir_gen_pointer_type(irb, scope, node), lval, result_loc); - case NodeTypeAnyFrameType: - return ir_lval_wrap(irb, scope, ir_gen_anyframe_type(irb, scope, node), lval, result_loc); - case NodeTypeStringLiteral: - return ir_lval_wrap(irb, scope, ir_gen_string_literal(irb, scope, node), lval, result_loc); - case NodeTypeUndefinedLiteral: - return ir_lval_wrap(irb, scope, ir_gen_undefined_literal(irb, scope, node), lval, result_loc); - case NodeTypeAsmExpr: - return ir_lval_wrap(irb, scope, ir_gen_asm_expr(irb, scope, node), lval, result_loc); - case NodeTypeNullLiteral: - return ir_lval_wrap(irb, scope, ir_gen_null_literal(irb, scope, node), lval, result_loc); - case NodeTypeIfErrorExpr: - return ir_gen_if_err_expr(irb, scope, node, lval, result_loc); - case NodeTypeIfOptional: - return ir_gen_if_optional_expr(irb, scope, node, lval, result_loc); - case NodeTypeSwitchExpr: - return ir_gen_switch_expr(irb, scope, node, lval, result_loc); - case NodeTypeCompTime: - return ir_expr_wrap(irb, scope, ir_gen_comptime(irb, scope, node, lval), result_loc); - case NodeTypeNoSuspend: - return ir_expr_wrap(irb, scope, ir_gen_nosuspend(irb, scope, node, lval), result_loc); - case NodeTypeErrorType: - return ir_lval_wrap(irb, scope, ir_gen_error_type(irb, scope, node), lval, result_loc); - case NodeTypeBreak: - return ir_lval_wrap(irb, scope, ir_gen_break(irb, scope, node), lval, result_loc); - case NodeTypeContinue: - return ir_lval_wrap(irb, scope, ir_gen_continue(irb, scope, node), lval, result_loc); - case NodeTypeUnreachable: - return ir_build_unreachable(irb, scope, node); - case NodeTypeDefer: - return ir_lval_wrap(irb, scope, ir_gen_defer(irb, scope, node), lval, result_loc); - case NodeTypeSliceExpr: - return ir_gen_slice(irb, scope, node, lval, result_loc); - case NodeTypeCatchExpr: - return ir_gen_catch(irb, scope, node, lval, result_loc); - case NodeTypeContainerDecl: - return ir_lval_wrap(irb, scope, ir_gen_container_decl(irb, scope, node), lval, result_loc); - case NodeTypeFnProto: - return ir_lval_wrap(irb, scope, ir_gen_fn_proto(irb, scope, node), lval, result_loc); - case NodeTypeErrorSetDecl: - return ir_lval_wrap(irb, scope, ir_gen_err_set_decl(irb, scope, node), lval, result_loc); - case NodeTypeResume: - return ir_lval_wrap(irb, scope, ir_gen_resume(irb, scope, node), lval, result_loc); - case NodeTypeAwaitExpr: - return ir_gen_await_expr(irb, scope, node, lval, result_loc); - case NodeTypeSuspend: - return ir_lval_wrap(irb, scope, ir_gen_suspend(irb, scope, node), lval, result_loc); - case NodeTypeEnumLiteral: - return ir_lval_wrap(irb, scope, ir_gen_enum_literal(irb, scope, node), lval, result_loc); - case NodeTypeInferredArrayType: - add_node_error(irb->codegen, node, - buf_sprintf("inferred array size invalid here")); - return irb->codegen->invalid_inst_src; - case NodeTypeAnyTypeField: - return ir_lval_wrap(irb, scope, - ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_anytype), lval, result_loc); - } - zig_unreachable(); -} - -static ResultLoc *no_result_loc(void) { - ResultLocNone *result_loc_none = heap::c_allocator.create(); - result_loc_none->base.id = ResultLocIdNone; - return &result_loc_none->base; -} - -static IrInstSrc *ir_gen_node_extra(IrBuilderSrc *irb, AstNode *node, Scope *scope, LVal lval, - ResultLoc *result_loc) -{ - if (lval == LValAssign) { - switch (node->type) { - case NodeTypeStructValueField: - case NodeTypeParamDecl: - case NodeTypeUsingNamespace: - case NodeTypeSwitchProng: - case NodeTypeSwitchRange: - case NodeTypeStructField: - case NodeTypeErrorSetField: - case NodeTypeFnDef: - case NodeTypeTestDecl: - zig_unreachable(); - - // cannot be assigned to - case NodeTypeBlock: - case NodeTypeGroupedExpr: - case NodeTypeBinOpExpr: - case NodeTypeIntLiteral: - case NodeTypeFloatLiteral: - case NodeTypeCharLiteral: - case NodeTypeIfBoolExpr: - case NodeTypeContainerInitExpr: - case NodeTypeVariableDeclaration: - case NodeTypeWhileExpr: - case NodeTypeForExpr: - case NodeTypeReturnExpr: - case NodeTypeBoolLiteral: - case NodeTypeArrayType: - case NodeTypePointerType: - case NodeTypeAnyFrameType: - case NodeTypeStringLiteral: - case NodeTypeUndefinedLiteral: - case NodeTypeAsmExpr: - case NodeTypeNullLiteral: - case NodeTypeIfErrorExpr: - case NodeTypeIfOptional: - case NodeTypeSwitchExpr: - case NodeTypeCompTime: - case NodeTypeNoSuspend: - case NodeTypeErrorType: - case NodeTypeBreak: - case NodeTypeContinue: - case NodeTypeUnreachable: - case NodeTypeDefer: - case NodeTypeSliceExpr: - case NodeTypeCatchExpr: - case NodeTypeContainerDecl: - case NodeTypeFnProto: - case NodeTypeErrorSetDecl: - case NodeTypeResume: - case NodeTypeAwaitExpr: - case NodeTypeSuspend: - case NodeTypeEnumLiteral: - case NodeTypeInferredArrayType: - case NodeTypeAnyTypeField: - case NodeTypePrefixOpExpr: - add_node_error(irb->codegen, node, - buf_sprintf("invalid left-hand side to assignment")); - return irb->codegen->invalid_inst_src; - - // @field can be assigned to - case NodeTypeFnCallExpr: - if (node->data.fn_call_expr.modifier == CallModifierBuiltin) { - AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr; - Buf *name = fn_ref_expr->data.symbol_expr.symbol; - auto entry = irb->codegen->builtin_fn_table.maybe_get(name); - - if (!entry) { - add_node_error(irb->codegen, node, - buf_sprintf("invalid builtin function: '%s'", buf_ptr(name))); - return irb->codegen->invalid_inst_src; - } - - if (entry->value->id == BuiltinFnIdField) { - break; - } - } - add_node_error(irb->codegen, node, - buf_sprintf("invalid left-hand side to assignment")); - return irb->codegen->invalid_inst_src; - - - // can be assigned to - case NodeTypeUnwrapOptional: - case NodeTypePtrDeref: - case NodeTypeFieldAccessExpr: - case NodeTypeArrayAccessExpr: - case NodeTypeSymbol: - break; - } - } - if (result_loc == nullptr) { - // Create a result location indicating there is none - but if one gets created - // it will be properly distributed. - result_loc = no_result_loc(); - ir_build_reset_result(irb, scope, node, result_loc); - } - Scope *child_scope; - if (irb->exec->is_inline || - (irb->exec->fn_entry != nullptr && irb->exec->fn_entry->child_scope == scope)) - { - child_scope = scope; - } else { - child_scope = &create_expr_scope(irb->codegen, node, scope)->base; - } - IrInstSrc *result = ir_gen_node_raw(irb, node, child_scope, lval, result_loc); - if (result == irb->codegen->invalid_inst_src) { - if (irb->exec->first_err_trace_msg == nullptr) { - irb->exec->first_err_trace_msg = irb->codegen->trace_err; - } - } - return result; -} - -static IrInstSrc *ir_gen_node(IrBuilderSrc *irb, AstNode *node, Scope *scope) { - return ir_gen_node_extra(irb, node, scope, LValNone, nullptr); -} - -static void invalidate_exec(IrExecutableSrc *exec, ErrorMsg *msg) { - if (exec->first_err_trace_msg != nullptr) - return; - - exec->first_err_trace_msg = msg; - - for (size_t i = 0; i < exec->tld_list.length; i += 1) { - exec->tld_list.items[i]->resolution = TldResolutionInvalid; - } -} - static void invalidate_exec_gen(IrExecutableGen *exec, ErrorMsg *msg) { if (exec->first_err_trace_msg != nullptr) return; @@ -10509,78 +2526,6 @@ static void invalidate_exec_gen(IrExecutableGen *exec, ErrorMsg *msg) { } -bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutableSrc *ir_executable) { - assert(node->owner); - - IrBuilderSrc ir_builder = {0}; - IrBuilderSrc *irb = &ir_builder; - - irb->codegen = codegen; - irb->exec = ir_executable; - irb->main_block_node = node; - - IrBasicBlockSrc *entry_block = ir_create_basic_block(irb, scope, "Entry"); - ir_set_cursor_at_end_and_append_block(irb, entry_block); - // Entry block gets a reference because we enter it to begin. - ir_ref_bb(irb->current_basic_block); - - IrInstSrc *result = ir_gen_node_extra(irb, node, scope, LValNone, nullptr); - - if (result == irb->codegen->invalid_inst_src) - return false; - - if (irb->exec->first_err_trace_msg != nullptr) { - codegen->trace_err = irb->exec->first_err_trace_msg; - return false; - } - - if (!instr_is_unreachable(result)) { - ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, result->base.source_node, result, nullptr)); - // no need for save_err_ret_addr because this cannot return error - ResultLocReturn *result_loc_ret = heap::c_allocator.create(); - result_loc_ret->base.id = ResultLocIdReturn; - ir_build_reset_result(irb, scope, node, &result_loc_ret->base); - ir_mark_gen(ir_build_end_expr(irb, scope, node, result, &result_loc_ret->base)); - ir_mark_gen(ir_build_return_src(irb, scope, result->base.source_node, result)); - } - - return true; -} - -bool ir_gen_fn(CodeGen *codegen, ZigFn *fn_entry) { - assert(fn_entry); - - IrExecutableSrc *ir_executable = fn_entry->ir_executable; - AstNode *body_node = fn_entry->body_node; - - assert(fn_entry->child_scope); - - return ir_gen(codegen, body_node, fn_entry->child_scope, ir_executable); -} - -static void ir_add_call_stack_errors_gen(CodeGen *codegen, IrExecutableGen *exec, ErrorMsg *err_msg, int limit) { - if (!exec || !exec->source_node || limit < 0) return; - add_error_note(codegen, err_msg, exec->source_node, buf_sprintf("called from here")); - - ir_add_call_stack_errors_gen(codegen, exec->parent_exec, err_msg, limit - 1); -} - -static void ir_add_call_stack_errors(CodeGen *codegen, IrExecutableSrc *exec, ErrorMsg *err_msg, int limit) { - if (!exec || !exec->source_node || limit < 0) return; - add_error_note(codegen, err_msg, exec->source_node, buf_sprintf("called from here")); - - ir_add_call_stack_errors_gen(codegen, exec->parent_exec, err_msg, limit - 1); -} - -static ErrorMsg *exec_add_error_node(CodeGen *codegen, IrExecutableSrc *exec, AstNode *source_node, Buf *msg) { - ErrorMsg *err_msg = add_node_error(codegen, source_node, msg); - invalidate_exec(exec, err_msg); - if (exec->parent_exec) { - ir_add_call_stack_errors(codegen, exec, err_msg, 10); - } - return err_msg; -} - static ErrorMsg *exec_add_error_node_gen(CodeGen *codegen, IrExecutableGen *exec, AstNode *source_node, Buf *msg) { ErrorMsg *err_msg = add_node_error(codegen, source_node, msg); invalidate_exec_gen(exec, err_msg); @@ -10605,11 +2550,6 @@ static ErrorMsg *ir_add_error(IrAnalyze *ira, IrInst *source_instruction, Buf *m return ir_add_error_node(ira, source_instruction->source_node, msg); } -static void ir_assert_impl(bool ok, IrInst *source_instruction, char const *file, unsigned int line) { - if (ok) return; - src_assert_impl(ok, source_instruction->source_node, file, line); -} - static void ir_assert_gen_impl(bool ok, IrInstGen *source_instruction, char const *file, unsigned int line) { if (ok) return; src_assert_impl(ok, source_instruction->base.source_node, file, line); @@ -13665,8 +5605,6 @@ Error ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, } if (codegen->verbose_ir) { - fprintf(stderr, "\nSource: "); - ast_render(stderr, node, 4); fprintf(stderr, "\n{ // (IR)\n"); ir_print_src(codegen, stderr, ir_executable, 2); fprintf(stderr, "}\n"); @@ -19482,7 +11420,7 @@ static IrInstGen *ir_analyze_instruction_extern(IrAnalyze *ira, IrInstSrcExtern } static bool exec_has_err_ret_trace(CodeGen *g, IrExecutableSrc *exec) { - ZigFn *fn_entry = exec_fn_entry(exec); + ZigFn *fn_entry = exec->fn_entry; return fn_entry != nullptr && fn_entry->calls_or_awaits_errorable_fn && g->have_err_ret_tracing; } @@ -20319,7 +12257,7 @@ static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node assert(param_decl_node->type == NodeTypeParamDecl); IrInstGen *casted_arg; - if (param_decl_node->data.param_decl.anytype_token == nullptr) { + if (param_decl_node->data.param_decl.anytype_token == 0) { AstNode *param_type_node = param_decl_node->data.param_decl.type; ZigType *param_type = ir_analyze_type_expr(ira, *exec_scope, param_type_node); if (type_is_invalid(param_type)) @@ -20362,7 +12300,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod casted_arg = arg; param_info_type = arg->value->type; } else { - if (param_decl_node->data.param_decl.anytype_token == nullptr) { + if (param_decl_node->data.param_decl.anytype_token == 0) { AstNode *param_type_node = param_decl_node->data.param_decl.type; ZigType *param_type = ir_analyze_type_expr(ira, *child_scope, param_type_node); if (type_is_invalid(param_type)) @@ -23593,6 +15531,25 @@ static IrInstGen *ir_analyze_instruction_slice_type(IrAnalyze *ira, IrInstSrcSli return result; } +static size_t find_asm_index(CodeGen *g, AstNode *node, AsmToken *tok, Buf *src_template) { + const char *ptr = buf_ptr(src_template) + tok->start + 2; + size_t len = tok->end - tok->start - 2; + size_t result = 0; + for (size_t i = 0; i < node->data.asm_expr.output_list.length; i += 1, result += 1) { + AsmOutput *asm_output = node->data.asm_expr.output_list.at(i); + if (buf_eql_mem(asm_output->asm_symbolic_name, ptr, len)) { + return result; + } + } + for (size_t i = 0; i < node->data.asm_expr.input_list.length; i += 1, result += 1) { + AsmInput *asm_input = node->data.asm_expr.input_list.at(i); + if (buf_eql_mem(asm_input->asm_symbolic_name, ptr, len)) { + return result; + } + } + return SIZE_MAX; +} + static IrInstGen *ir_analyze_instruction_asm(IrAnalyze *ira, IrInstSrcAsm *asm_instruction) { Error err; @@ -27066,8 +19023,10 @@ static IrInstGen *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstSrcCImpo return ira->codegen->invalid_inst_gen; ZigPackage *cur_scope_pkg = scope_package(instruction->base.base.scope); - Buf *namespace_name = buf_sprintf("%s.cimport:%" ZIG_PRI_usize ":%" ZIG_PRI_usize, - buf_ptr(&cur_scope_pkg->pkg_path), node->line + 1, node->column + 1); + RootStruct *root_struct = node->owner->data.structure.root_struct; + TokenLoc tok_loc = root_struct->token_locs[node->main_token]; + Buf *namespace_name = buf_sprintf("%s.cimport:%" PRIu32 ":%" PRIu32, + buf_ptr(&cur_scope_pkg->pkg_path), tok_loc.line + 1, tok_loc.column + 1); ZigPackage *cimport_pkg = new_anonymous_package(); cimport_pkg->package_table.put(buf_create_from_str("builtin"), ira->codegen->compile_var_package); @@ -27095,12 +19054,14 @@ static IrInstGen *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstSrcCImpo } for (size_t i = 0; i < errors_len; i += 1) { Stage2ErrorMsg *clang_err = &errors_ptr[i]; - // Clang can emit "too many errors, stopping now", in which case `source` and `filename_ptr` are null + // Clang can emit "too many errors, stopping now", in which case + // `source` and `filename_ptr` are null if (clang_err->source && clang_err->filename_ptr) { ErrorMsg *err_msg = err_msg_create_with_offset( clang_err->filename_ptr ? - buf_create_from_mem(clang_err->filename_ptr, clang_err->filename_len) : buf_alloc(), - clang_err->line, clang_err->column, clang_err->offset, clang_err->source, + buf_create_from_mem(clang_err->filename_ptr, clang_err->filename_len) : + buf_alloc(), + clang_err->offset, clang_err->source, buf_create_from_mem(clang_err->msg_ptr, clang_err->msg_len)); err_msg_add_note(parent_err_msg, err_msg); } @@ -27225,7 +19186,7 @@ static IrInstGen *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstSrcEmb } IrInstGen *result = ir_const(ira, &instruction->base.base, nullptr); - init_const_str_lit(ira->codegen, result->value, file_contents); + init_const_str_lit(ira->codegen, result->value, file_contents, true); return result; } @@ -31851,6 +23812,22 @@ static IrInstGen *ir_analyze_instruction_has_decl(IrAnalyze *ira, IrInstSrcHasDe return ir_const_bool(ira, &instruction->base.base, true); } +static void populate_invalid_variable_in_scope(CodeGen *g, Scope *scope, AstNode *node, Buf *var_name) { + ScopeDecls *scope_decls = nullptr; + while (scope != nullptr) { + if (scope->id == ScopeIdDecls) { + scope_decls = reinterpret_cast(scope); + } + scope = scope->parent; + } + TldVar *tld_var = heap::c_allocator.create(); + init_tld(&tld_var->base, TldIdVar, var_name, VisibModPub, node, &scope_decls->base); + tld_var->base.resolution = TldResolutionInvalid; + tld_var->var = add_variable(g, node, &scope_decls->base, var_name, false, + g->invalid_inst_gen->value, &tld_var->base, g->builtin_types.entry_invalid); + scope_decls->decl_table.put(var_name, &tld_var->base); +} + static IrInstGen *ir_analyze_instruction_undeclared_ident(IrAnalyze *ira, IrInstSrcUndeclaredIdent *instruction) { // put a variable of same name with invalid type in global scope // so that future references to this same name will find a variable with an invalid type @@ -32169,7 +24146,8 @@ static IrInstGen *ir_analyze_instruction_src(IrAnalyze *ira, IrInstSrcSrc *instr fields[0]->special = ConstValSpecialStatic; ZigType *import = instruction->base.base.source_node->owner; - Buf *path = import->data.structure.root_struct->path; + RootStruct *root_struct = import->data.structure.root_struct; + Buf *path = root_struct->path; ZigValue *file_name = create_const_str_lit(ira->codegen, path)->data.x_ptr.data.ref.pointee; init_const_slice(ira->codegen, fields[0], file_name, 0, buf_len(path), true); fields[0]->type = u8_slice; @@ -32182,17 +24160,20 @@ static IrInstGen *ir_analyze_instruction_src(IrAnalyze *ira, IrInstSrcSrc *instr init_const_slice(ira->codegen, fields[1], fn_name, 0, buf_len(&fn_entry->symbol_name), true); fields[1]->type = u8_slice; + + TokenLoc tok_loc = root_struct->token_locs[instruction->base.base.source_node->main_token]; + // line: u32 ensure_field_index(source_location_type, "line", 2); fields[2]->special = ConstValSpecialStatic; fields[2]->type = ira->codegen->builtin_types.entry_u32; - bigint_init_unsigned(&fields[2]->data.x_bigint, instruction->base.base.source_node->line + 1); + bigint_init_unsigned(&fields[2]->data.x_bigint, tok_loc.line + 1); // column: u32 ensure_field_index(source_location_type, "column", 3); fields[3]->special = ConstValSpecialStatic; fields[3]->type = ira->codegen->builtin_types.entry_u32; - bigint_init_unsigned(&fields[3]->data.x_bigint, instruction->base.base.source_node->column + 1); + bigint_init_unsigned(&fields[3]->data.x_bigint, tok_loc.column + 1); return ir_const_move(ira, &instruction->base.base, result); } @@ -32539,20 +24520,6 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutableSrc *old_exec, IrExecutableGen old_instruction->src(); fprintf(stderr, "~ "); ir_print_inst_src(codegen, stderr, old_instruction, 0); - bool want_break = false; - if (ira->break_debug_id == old_instruction->base.debug_id) { - want_break = true; - } else if (old_instruction->base.source_node != nullptr) { - for (size_t i = 0; i < dbg_ir_breakpoints_count; i += 1) { - if (dbg_ir_breakpoints_buf[i].line == old_instruction->base.source_node->line + 1 && - buf_ends_with_str(old_instruction->base.source_node->owner->data.structure.root_struct->path, - dbg_ir_breakpoints_buf[i].src_file)) - { - want_break = true; - } - } - } - if (want_break) BREAKPOINT; } IrInstGen *new_instruction = ir_analyze_instruction_base(ira, old_instruction); if (new_instruction != nullptr) { @@ -33541,11 +25508,3 @@ void IrAnalyze::dump() { ir_print_basic_block_gen(this->codegen, stderr, this->new_irb.current_basic_block, 1); } } - -void dbg_ir_break(const char *src_file, uint32_t line) { - dbg_ir_breakpoints_buf[dbg_ir_breakpoints_count] = {src_file, line}; - dbg_ir_breakpoints_count += 1; -} -void dbg_ir_clear(void) { - dbg_ir_breakpoints_count = 0; -} diff --git a/src/stage1/ir.hpp b/src/stage1/ir.hpp index 3686771287..66f0b9a99b 100644 --- a/src/stage1/ir.hpp +++ b/src/stage1/ir.hpp @@ -10,9 +10,6 @@ #include "all_types.hpp" -bool ir_gen(CodeGen *g, AstNode *node, Scope *scope, IrExecutableSrc *ir_executable); -bool ir_gen_fn(CodeGen *g, ZigFn *fn_entry); - IrInstGen *ir_create_alloca(CodeGen *g, Scope *scope, AstNode *source_node, ZigFn *fn, ZigType *var_type, const char *name_hint); @@ -33,8 +30,4 @@ struct IrAnalyze; ZigValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ZigValue *const_val, AstNode *source_node); -// for debugging purposes -void dbg_ir_break(const char *src_file, uint32_t line); -void dbg_ir_clear(void); - #endif diff --git a/src/stage1/parser.cpp b/src/stage1/parser.cpp index 19cd977c71..51acc6a566 100644 --- a/src/stage1/parser.cpp +++ b/src/stage1/parser.cpp @@ -16,28 +16,34 @@ struct ParseContext { Buf *buf; - size_t current_token; - ZigList *tokens; + // Shortcut to `owner->data.structure.root_struct->token_ids`. + TokenId *token_ids; + // Shortcut to `owner->data.structure.root_struct->token_locs`. + TokenLoc *token_locs; ZigType *owner; + TokenIndex current_token; ErrColor err_color; + // Shortcut to `owner->data.structure.root_struct->token_count`. + uint32_t token_count; }; struct PtrPayload { - Token *asterisk; - Token *payload; + TokenIndex asterisk; + TokenIndex payload; }; struct PtrIndexPayload { - Token *asterisk; - Token *payload; - Token *index; + TokenIndex asterisk; + TokenIndex payload; + TokenIndex index; }; static AstNode *ast_parse_root(ParseContext *pc); static AstNodeContainerDecl ast_parse_container_members(ParseContext *pc); static AstNode *ast_parse_test_decl(ParseContext *pc); static AstNode *ast_parse_top_level_comptime(ParseContext *pc); -static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, Buf *doc_comments); +static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, + TokenIndex doc_comments); static AstNode *ast_parse_fn_proto(ParseContext *pc); static AstNode *ast_parse_var_decl(ParseContext *pc); static AstNode *ast_parse_container_field(ParseContext *pc); @@ -87,8 +93,8 @@ static AsmOutput *ast_parse_asm_output_item(ParseContext *pc); static AstNode *ast_parse_asm_input(ParseContext *pc); static AsmInput *ast_parse_asm_input_item(ParseContext *pc); static AstNode *ast_parse_asm_clobbers(ParseContext *pc); -static Token *ast_parse_break_label(ParseContext *pc); -static Token *ast_parse_block_label(ParseContext *pc); +static TokenIndex ast_parse_break_label(ParseContext *pc); +static TokenIndex ast_parse_block_label(ParseContext *pc); static AstNode *ast_parse_field_init(ParseContext *pc); static AstNode *ast_parse_while_continue_expr(ParseContext *pc); static AstNode *ast_parse_link_section(ParseContext *pc); @@ -98,7 +104,7 @@ static AstNode *ast_parse_param_type(ParseContext *pc); static AstNode *ast_parse_if_prefix(ParseContext *pc); static AstNode *ast_parse_while_prefix(ParseContext *pc); static AstNode *ast_parse_for_prefix(ParseContext *pc); -static Token *ast_parse_payload(ParseContext *pc); +static TokenIndex ast_parse_payload(ParseContext *pc); static Optional ast_parse_ptr_payload(ParseContext *pc); static Optional ast_parse_ptr_index_payload(ParseContext *pc); static AstNode *ast_parse_switch_prong(ParseContext *pc); @@ -122,27 +128,25 @@ static AstNode *ast_parse_byte_align(ParseContext *pc); ATTRIBUTE_PRINTF(3, 4) ATTRIBUTE_NORETURN -static void ast_error(ParseContext *pc, Token *token, const char *format, ...) { +static void ast_error(ParseContext *pc, TokenIndex token, const char *format, ...) { va_list ap; va_start(ap, format); Buf *msg = buf_vprintf(format, ap); va_end(ap); - - ErrorMsg *err = err_msg_create_with_line(pc->owner->data.structure.root_struct->path, - token->start_line, token->start_column, - pc->owner->data.structure.root_struct->source_code, - pc->owner->data.structure.root_struct->line_offsets, msg); - err->line_start = token->start_line; - err->column_start = token->start_column; + RootStruct *root_struct = pc->owner->data.structure.root_struct; + assert(token < root_struct->token_count); + uint32_t byte_offset = root_struct->token_locs[token].offset; + ErrorMsg *err = err_msg_create_with_offset(root_struct->path, + byte_offset, buf_ptr(root_struct->source_code), msg); print_err_msg(err, pc->err_color); exit(EXIT_FAILURE); } ATTRIBUTE_NORETURN -static void ast_invalid_token_error(ParseContext *pc, Token *token) { - ast_error(pc, token, "invalid token: '%s'", token_name(token->id)); +static void ast_invalid_token_error(ParseContext *pc, TokenIndex token) { + ast_error(pc, token, "invalid token: '%s'", token_name(pc->token_ids[token])); } static AstNode *ast_create_node_no_line_info(ParseContext *pc, NodeType type) { @@ -152,48 +156,44 @@ static AstNode *ast_create_node_no_line_info(ParseContext *pc, NodeType type) { return node; } -static AstNode *ast_create_node(ParseContext *pc, NodeType type, Token *first_token) { +static AstNode *ast_create_node(ParseContext *pc, NodeType type, TokenIndex first_token) { assert(first_token); AstNode *node = ast_create_node_no_line_info(pc, type); - node->line = first_token->start_line; - node->column = first_token->start_column; + node->main_token = first_token; return node; } static AstNode *ast_create_node_copy_line_info(ParseContext *pc, NodeType type, AstNode *from) { assert(from); AstNode *node = ast_create_node_no_line_info(pc, type); - node->line = from->line; - node->column = from->column; + node->main_token = from->main_token; return node; } -static Token *peek_token_i(ParseContext *pc, size_t i) { - return &pc->tokens->at(pc->current_token + i); +static TokenIndex peek_token(ParseContext *pc) { + return pc->current_token; } -static Token *peek_token(ParseContext *pc) { - return peek_token_i(pc, 0); -} - -static Token *eat_token(ParseContext *pc) { - Token *res = peek_token(pc); +static TokenIndex eat_token(ParseContext *pc) { + TokenIndex res = peek_token(pc); pc->current_token += 1; return res; } -static Token *eat_token_if(ParseContext *pc, TokenId id) { - Token *res = peek_token(pc); - if (res->id == id) +static TokenIndex eat_token_if(ParseContext *pc, TokenId id) { + TokenIndex res = peek_token(pc); + if (pc->token_ids[res] == id) { return eat_token(pc); + } - return nullptr; + return 0; } -static Token *expect_token(ParseContext *pc, TokenId id) { - Token *res = eat_token(pc); - if (res->id != id) - ast_error(pc, res, "expected token '%s', found '%s'", token_name(id), token_name(res->id)); +static TokenIndex expect_token(ParseContext *pc, TokenId id) { + TokenIndex res = eat_token(pc); + TokenId actual_id = pc->token_ids[res]; + if (actual_id != id) + ast_error(pc, res, "expected token '%s', found '%s'", token_name(id), token_name(actual_id)); return res; } @@ -202,23 +202,23 @@ static void put_back_token(ParseContext *pc) { pc->current_token -= 1; } -static Buf *token_buf(Token *token) { - if (token == nullptr) +static Buf *token_buf(ParseContext *pc, TokenIndex token) { + if (token == 0) return nullptr; - assert(token->id == TokenIdStringLiteral || token->id == TokenIdMultilineStringLiteral || token->id == TokenIdSymbol); - return &token->data.str_lit.str; + + RootStruct *root_struct = pc->owner->data.structure.root_struct; + if (root_struct->token_ids[token] == TokenIdIdentifier) { + return token_identifier_buf(root_struct, token); + } else if (root_struct->token_ids[token] == TokenIdStringLiteral) { + return token_string_literal_buf(root_struct, token); + } else { + zig_unreachable(); + } } -static BigInt *token_bigint(Token *token) { - assert(token->id == TokenIdIntLiteral); - return &token->data.int_lit.bigint; -} - -static AstNode *token_symbol(ParseContext *pc, Token *token) { - assert(token->id == TokenIdSymbol); - AstNode *res = ast_create_node(pc, NodeTypeSymbol, token); - res->data.symbol_expr.symbol = token_buf(token); - return res; +static AstNode *token_identifier(ParseContext *pc, TokenIndex token) { + assert(pc->token_ids[token] == TokenIdIdentifier); + return ast_create_node(pc, NodeTypeIdentifier, token); } // (Rule SEP)* Rule? @@ -231,7 +231,7 @@ static ZigList ast_parse_list(ParseContext *pc, TokenId sep, T *(*parser)(P break; res.append(curr); - if (eat_token_if(pc, sep) == nullptr) + if (eat_token_if(pc, sep) == 0) break; } @@ -355,22 +355,22 @@ static AstNode *ast_parse_if_expr_helper(ParseContext *pc, AstNode *(*body_parse return nullptr; AstNode *body = ast_expect(pc, body_parser); - Token *err_payload = nullptr; + TokenIndex err_payload = 0; AstNode *else_body = nullptr; - if (eat_token_if(pc, TokenIdKeywordElse) != nullptr) { + if (eat_token_if(pc, TokenIdKeywordElse) != 0) { err_payload = ast_parse_payload(pc); else_body = ast_expect(pc, body_parser); } assert(res->type == NodeTypeIfOptional); - if (err_payload != nullptr) { + if (err_payload != 0) { AstNodeTestExpr old = res->data.test_expr; res->type = NodeTypeIfErrorExpr; res->data.if_err_expr.target_node = old.target_node; res->data.if_err_expr.var_is_ptr = old.var_is_ptr; res->data.if_err_expr.var_symbol = old.var_symbol; res->data.if_err_expr.then_node = body; - res->data.if_err_expr.err_symbol = token_buf(err_payload); + res->data.if_err_expr.err_symbol = token_buf(pc, err_payload); res->data.if_err_expr.else_node = else_body; return res; } @@ -395,22 +395,22 @@ static AstNode *ast_parse_loop_expr_helper( AstNode *(*for_parser)(ParseContext *), AstNode *(*while_parser)(ParseContext *) ) { - Token *inline_token = eat_token_if(pc, TokenIdKeywordInline); + TokenIndex inline_token = eat_token_if(pc, TokenIdKeywordInline); AstNode *for_expr = for_parser(pc); if (for_expr != nullptr) { assert(for_expr->type == NodeTypeForExpr); - for_expr->data.for_expr.is_inline = inline_token != nullptr; + for_expr->data.for_expr.is_inline = inline_token != 0; return for_expr; } AstNode *while_expr = while_parser(pc); if (while_expr != nullptr) { assert(while_expr->type == NodeTypeWhileExpr); - while_expr->data.while_expr.is_inline = inline_token != nullptr; + while_expr->data.while_expr.is_inline = inline_token != 0; return while_expr; } - if (inline_token != nullptr) + if (inline_token != 0) ast_invalid_token_error(pc, peek_token(pc)); return nullptr; } @@ -423,7 +423,7 @@ static AstNode *ast_parse_for_expr_helper(ParseContext *pc, AstNode *(*body_pars AstNode *body = ast_expect(pc, body_parser); AstNode *else_body = nullptr; - if (eat_token_if(pc, TokenIdKeywordElse) != nullptr) + if (eat_token_if(pc, TokenIdKeywordElse) != 0) else_body = ast_expect(pc, body_parser); assert(res->type == NodeTypeForExpr); @@ -439,24 +439,24 @@ static AstNode *ast_parse_while_expr_helper(ParseContext *pc, AstNode *(*body_pa return nullptr; AstNode *body = ast_expect(pc, body_parser); - Token *err_payload = nullptr; + TokenIndex err_payload = 0; AstNode *else_body = nullptr; - if (eat_token_if(pc, TokenIdKeywordElse) != nullptr) { + if (eat_token_if(pc, TokenIdKeywordElse) != 0) { err_payload = ast_parse_payload(pc); else_body = ast_expect(pc, body_parser); } assert(res->type == NodeTypeWhileExpr); res->data.while_expr.body = body; - res->data.while_expr.err_symbol = token_buf(err_payload); + res->data.while_expr.err_symbol = token_buf(pc, err_payload); res->data.while_expr.else_node = else_body; return res; } template AstNode *ast_parse_bin_op_simple(ParseContext *pc) { - Token *op_token = eat_token_if(pc, id); - if (op_token == nullptr) + TokenIndex op_token = eat_token_if(pc, id); + if (op_token == 0) return nullptr; AstNode *res = ast_create_node(pc, NodeTypeBinOpExpr, op_token); @@ -464,20 +464,25 @@ AstNode *ast_parse_bin_op_simple(ParseContext *pc) { return res; } -AstNode *ast_parse(Buf *buf, ZigList *tokens, ZigType *owner, ErrColor err_color) { +AstNode *ast_parse(Buf *buf, ZigType *owner, ErrColor err_color) { + RootStruct *root_struct = owner->data.structure.root_struct; + ParseContext pc = {}; pc.err_color = err_color; pc.owner = owner; pc.buf = buf; - pc.tokens = tokens; + pc.token_ids = root_struct->token_ids; + pc.token_locs = root_struct->token_locs; + pc.token_count = root_struct->token_count; + pc.current_token = 1; // Skip over the first (invalid) token. return ast_parse_root(&pc); } // Root <- skip ContainerMembers eof static AstNode *ast_parse_root(ParseContext *pc) { - Token *first = peek_token(pc); + TokenIndex first = peek_token(pc); AstNodeContainerDecl members = ast_parse_container_members(pc); - if (pc->current_token != pc->tokens->length - 1) + if (pc->current_token != pc->token_count - 1) ast_invalid_token_error(pc, peek_token(pc)); AstNode *node = ast_create_node(pc, NodeTypeContainerDecl, first); @@ -486,70 +491,26 @@ static AstNode *ast_parse_root(ParseContext *pc) { node->data.container_decl.layout = ContainerLayoutAuto; node->data.container_decl.kind = ContainerKindStruct; node->data.container_decl.is_root = true; - if (buf_len(&members.doc_comments) != 0) { - node->data.container_decl.doc_comments = members.doc_comments; - } + node->data.container_decl.doc_comments = members.doc_comments; return node; } -static Token *ast_parse_multiline_string_literal(ParseContext *pc, Buf *buf) { - Token *first_str_token = nullptr; - Token *str_token = nullptr; - while ((str_token = eat_token_if(pc, TokenIdMultilineStringLiteral))) { - if (first_str_token == nullptr) { - first_str_token = str_token; - } - if (buf->list.length == 0) { - buf_resize(buf, 0); - } - buf_append_buf(buf, token_buf(str_token)); - - // Ignore inline comments - size_t cur_token = pc->current_token; - while (eat_token_if(pc, TokenIdDocComment)); - - // Lookahead to see if there's another multilne string literal, - // if not, we have to revert back to before the doc comment - if (peek_token(pc)->id != TokenIdMultilineStringLiteral) { - pc->current_token = cur_token; - } else { - buf_append_char(buf, '\n'); // Add a newline between comments - } +static TokenIndex ast_parse_multi_tok(ParseContext *pc, TokenId token_id) { + TokenIndex first_token = eat_token_if(pc, token_id); + TokenIndex token = first_token; + while (token != 0) { + token = eat_token_if(pc, token_id); } - return first_str_token; + return first_token; } -static Token *ast_parse_doc_comments(ParseContext *pc, Buf *buf) { - Token *first_doc_token = nullptr; - Token *doc_token = nullptr; - while ((doc_token = eat_token_if(pc, TokenIdDocComment))) { - if (first_doc_token == nullptr) { - first_doc_token = doc_token; - } - if (buf->list.length == 0) { - buf_resize(buf, 0); - } - // chops off '///' but leaves '\n' - buf_append_mem(buf, buf_ptr(pc->buf) + doc_token->start_pos + 3, - doc_token->end_pos - doc_token->start_pos - 3); - } - return first_doc_token; +static TokenIndex ast_parse_doc_comments(ParseContext *pc) { + return ast_parse_multi_tok(pc, TokenIdDocComment); } -static void ast_parse_container_doc_comments(ParseContext *pc, Buf *buf) { - if (buf_len(buf) != 0 && peek_token(pc)->id == TokenIdContainerDocComment) { - buf_append_char(buf, '\n'); - } - Token *doc_token = nullptr; - while ((doc_token = eat_token_if(pc, TokenIdContainerDocComment))) { - if (buf->list.length == 0) { - buf_resize(buf, 0); - } - // chops off '//!' but leaves '\n' - buf_append_mem(buf, buf_ptr(pc->buf) + doc_token->start_pos + 3, - doc_token->end_pos - doc_token->start_pos - 3); - } +static TokenIndex ast_parse_container_doc_comments(ParseContext *pc) { + return ast_parse_multi_tok(pc, TokenIdContainerDocComment); } enum ContainerFieldState { @@ -570,14 +531,11 @@ enum ContainerFieldState { // / static AstNodeContainerDecl ast_parse_container_members(ParseContext *pc) { AstNodeContainerDecl res = {}; - Buf tld_doc_comment_buf = BUF_INIT; - buf_resize(&tld_doc_comment_buf, 0); ContainerFieldState field_state = ContainerFieldStateNone; - Token *first_token = nullptr; + TokenIndex first_token = 0; + res.doc_comments = ast_parse_container_doc_comments(pc); for (;;) { - ast_parse_container_doc_comments(pc, &tld_doc_comment_buf); - - Token *peeked_token = peek_token(pc); + TokenIndex peeked_token = peek_token(pc); AstNode *test_decl = ast_parse_test_decl(pc); if (test_decl != nullptr) { @@ -599,15 +557,14 @@ static AstNodeContainerDecl ast_parse_container_members(ParseContext *pc) { continue; } - Buf doc_comment_buf = BUF_INIT; - ast_parse_doc_comments(pc, &doc_comment_buf); + TokenIndex first_doc_token = ast_parse_doc_comments(pc); peeked_token = peek_token(pc); - Token *visib_token = eat_token_if(pc, TokenIdKeywordPub); - VisibMod visib_mod = visib_token != nullptr ? VisibModPub : VisibModPrivate; + TokenIndex visib_token = eat_token_if(pc, TokenIdKeywordPub); + VisibMod visib_mod = (visib_token != 0) ? VisibModPub : VisibModPrivate; - AstNode *top_level_decl = ast_parse_top_level_decl(pc, visib_mod, &doc_comment_buf); + AstNode *top_level_decl = ast_parse_top_level_decl(pc, visib_mod, first_doc_token); if (top_level_decl != nullptr) { if (field_state == ContainerFieldStateSeen) { field_state = ContainerFieldStateEnd; @@ -617,11 +574,11 @@ static AstNodeContainerDecl ast_parse_container_members(ParseContext *pc) { continue; } - if (visib_token != nullptr) { + if (visib_token != 0) { ast_error(pc, peek_token(pc), "expected function or variable declaration after pub"); } - Token *comptime_token = eat_token_if(pc, TokenIdKeywordCompTime); + TokenIndex comptime_token = eat_token_if(pc, TokenIdKeywordCompTime); AstNode *container_field = ast_parse_container_field(pc); if (container_field != nullptr) { @@ -636,10 +593,10 @@ static AstNodeContainerDecl ast_parse_container_members(ParseContext *pc) { } assert(container_field->type == NodeTypeStructField); - container_field->data.struct_field.doc_comments = doc_comment_buf; + container_field->data.struct_field.doc_comments = first_doc_token; container_field->data.struct_field.comptime_token = comptime_token; res.fields.append(container_field); - if (eat_token_if(pc, TokenIdComma) != nullptr) { + if (eat_token_if(pc, TokenIdComma) != 0) { continue; } else { break; @@ -648,33 +605,32 @@ static AstNodeContainerDecl ast_parse_container_members(ParseContext *pc) { break; } - res.doc_comments = tld_doc_comment_buf; return res; } // TestDecl <- KEYWORD_test STRINGLITERALSINGLE Block static AstNode *ast_parse_test_decl(ParseContext *pc) { - Token *test = eat_token_if(pc, TokenIdKeywordTest); - if (test == nullptr) + TokenIndex test = eat_token_if(pc, TokenIdKeywordTest); + if (test == 0) return nullptr; - Token *name = eat_token_if(pc, TokenIdStringLiteral); + TokenIndex name = eat_token_if(pc, TokenIdStringLiteral); AstNode *block = ast_expect(pc, ast_parse_block); AstNode *res = ast_create_node(pc, NodeTypeTestDecl, test); - res->data.test_decl.name = name ? token_buf(name) : nullptr; + res->data.test_decl.name = name ? token_buf(pc, name) : nullptr; res->data.test_decl.body = block; return res; } // TopLevelComptime <- KEYWORD_comptime BlockExpr static AstNode *ast_parse_top_level_comptime(ParseContext *pc) { - Token *comptime = eat_token_if(pc, TokenIdKeywordCompTime); - if (comptime == nullptr) + TokenIndex comptime = eat_token_if(pc, TokenIdKeywordCompTime); + if (comptime == 0) return nullptr; // 1 token lookahead because it could be a comptime struct field - Token *lbrace = peek_token(pc); - if (lbrace->id != TokenIdLBrace) { + TokenIndex lbrace = peek_token(pc); + if (pc->token_ids[lbrace] != TokenIdLBrace) { put_back_token(pc); return nullptr; } @@ -689,39 +645,40 @@ static AstNode *ast_parse_top_level_comptime(ParseContext *pc) { // <- (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE? / (KEYWORD_inline / KEYWORD_noinline))? FnProto (SEMICOLON / Block) // / (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE?)? KEYWORD_threadlocal? VarDecl // / KEYWORD_use Expr SEMICOLON -static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, Buf *doc_comments) { - Token *first = eat_token_if(pc, TokenIdKeywordExport); - if (first == nullptr) +static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, + TokenIndex doc_comments) +{ + TokenIndex first = eat_token_if(pc, TokenIdKeywordExport); + if (first == 0) first = eat_token_if(pc, TokenIdKeywordExtern); - if (first == nullptr) + if (first == 0) first = eat_token_if(pc, TokenIdKeywordInline); - if (first == nullptr) + if (first == 0) first = eat_token_if(pc, TokenIdKeywordNoInline); - if (first != nullptr) { - Token *lib_name = nullptr; - if (first->id == TokenIdKeywordExtern) + if (first != 0) { + TokenIndex lib_name = 0; + if (pc->token_ids[first] == TokenIdKeywordExtern) lib_name = eat_token_if(pc, TokenIdStringLiteral); - if (first->id != TokenIdKeywordNoInline && first->id != TokenIdKeywordInline) { - Token *thread_local_kw = eat_token_if(pc, TokenIdKeywordThreadLocal); + if (pc->token_ids[first] != TokenIdKeywordNoInline && pc->token_ids[first] != TokenIdKeywordInline) { + TokenIndex thread_local_kw = eat_token_if(pc, TokenIdKeywordThreadLocal); AstNode *var_decl = ast_parse_var_decl(pc); if (var_decl != nullptr) { assert(var_decl->type == NodeTypeVariableDeclaration); - if (first->id == TokenIdKeywordExtern && var_decl->data.variable_declaration.expr != nullptr) { + if (pc->token_ids[first] == TokenIdKeywordExtern && var_decl->data.variable_declaration.expr != nullptr) { ast_error(pc, first, "extern variables have no initializers"); } - var_decl->line = first->start_line; - var_decl->column = first->start_column; + var_decl->main_token = first; var_decl->data.variable_declaration.threadlocal_tok = thread_local_kw; var_decl->data.variable_declaration.visib_mod = visib_mod; - var_decl->data.variable_declaration.doc_comments = *doc_comments; - var_decl->data.variable_declaration.is_extern = first->id == TokenIdKeywordExtern; - var_decl->data.variable_declaration.is_export = first->id == TokenIdKeywordExport; - var_decl->data.variable_declaration.lib_name = token_buf(lib_name); + var_decl->data.variable_declaration.doc_comments = doc_comments; + var_decl->data.variable_declaration.is_extern = pc->token_ids[first] == TokenIdKeywordExtern; + var_decl->data.variable_declaration.is_export = pc->token_ids[first] == TokenIdKeywordExport; + var_decl->data.variable_declaration.lib_name = token_buf(pc, lib_name); return var_decl; } - if (thread_local_kw != nullptr) + if (thread_local_kw != 0) put_back_token(pc); } @@ -732,14 +689,13 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, B expect_token(pc, TokenIdSemicolon); assert(fn_proto->type == NodeTypeFnProto); - fn_proto->line = first->start_line; - fn_proto->column = first->start_column; + fn_proto->main_token = first; fn_proto->data.fn_proto.visib_mod = visib_mod; - fn_proto->data.fn_proto.doc_comments = *doc_comments; + fn_proto->data.fn_proto.doc_comments = doc_comments; if (!fn_proto->data.fn_proto.is_extern) - fn_proto->data.fn_proto.is_extern = first->id == TokenIdKeywordExtern; - fn_proto->data.fn_proto.is_export = first->id == TokenIdKeywordExport; - switch (first->id) { + fn_proto->data.fn_proto.is_extern = pc->token_ids[first] == TokenIdKeywordExtern; + fn_proto->data.fn_proto.is_export = pc->token_ids[first] == TokenIdKeywordExport; + switch (pc->token_ids[first]) { case TokenIdKeywordInline: fn_proto->data.fn_proto.fn_inline = FnInlineAlways; break; @@ -750,7 +706,7 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, B fn_proto->data.fn_proto.fn_inline = FnInlineAuto; break; } - fn_proto->data.fn_proto.lib_name = token_buf(lib_name); + fn_proto->data.fn_proto.lib_name = token_buf(pc, lib_name); AstNode *res = fn_proto; if (body != nullptr) { @@ -769,17 +725,17 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, B ast_invalid_token_error(pc, peek_token(pc)); } - Token *thread_local_kw = eat_token_if(pc, TokenIdKeywordThreadLocal); + TokenIndex thread_local_kw = eat_token_if(pc, TokenIdKeywordThreadLocal); AstNode *var_decl = ast_parse_var_decl(pc); if (var_decl != nullptr) { assert(var_decl->type == NodeTypeVariableDeclaration); var_decl->data.variable_declaration.visib_mod = visib_mod; - var_decl->data.variable_declaration.doc_comments = *doc_comments; + var_decl->data.variable_declaration.doc_comments = doc_comments; var_decl->data.variable_declaration.threadlocal_tok = thread_local_kw; return var_decl; } - if (thread_local_kw != nullptr) + if (thread_local_kw != 0) put_back_token(pc); AstNode *fn_proto = ast_parse_fn_proto(pc); @@ -790,7 +746,7 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, B assert(fn_proto->type == NodeTypeFnProto); fn_proto->data.fn_proto.visib_mod = visib_mod; - fn_proto->data.fn_proto.doc_comments = *doc_comments; + fn_proto->data.fn_proto.doc_comments = doc_comments; AstNode *res = fn_proto; if (body != nullptr) { res = ast_create_node_copy_line_info(pc, NodeTypeFnDef, fn_proto); @@ -802,8 +758,8 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, B return res; } - Token *usingnamespace = eat_token_if(pc, TokenIdKeywordUsingNamespace); - if (usingnamespace != nullptr) { + TokenIndex usingnamespace = eat_token_if(pc, TokenIdKeywordUsingNamespace); + if (usingnamespace != 0) { AstNode *expr = ast_expect(pc, ast_parse_expr); expect_token(pc, TokenIdSemicolon); @@ -818,12 +774,12 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, B // FnProto <- KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? EXCLAMATIONMARK? (KEYWORD_anytype / TypeExpr) static AstNode *ast_parse_fn_proto(ParseContext *pc) { - Token *first = eat_token_if(pc, TokenIdKeywordFn); - if (first == nullptr) { + TokenIndex first = eat_token_if(pc, TokenIdKeywordFn); + if (first == 0) { return nullptr; } - Token *identifier = eat_token_if(pc, TokenIdSymbol); + TokenIndex identifier = eat_token_if(pc, TokenIdIdentifier); expect_token(pc, TokenIdLParen); ZigList params = ast_parse_list(pc, TokenIdComma, ast_parse_param_decl); expect_token(pc, TokenIdRParen); @@ -831,29 +787,29 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc) { AstNode *align_expr = ast_parse_byte_align(pc); AstNode *section_expr = ast_parse_link_section(pc); AstNode *callconv_expr = ast_parse_callconv(pc); - Token *exmark = nullptr; + TokenIndex exmark = 0; AstNode *return_type = nullptr; exmark = eat_token_if(pc, TokenIdBang); return_type = ast_parse_type_expr(pc); if (return_type == nullptr) { - Token *next = peek_token(pc); + TokenIndex next = peek_token(pc); ast_error( pc, next, "expected return type (use 'void' to return nothing), found: '%s'", - token_name(next->id) + token_name(pc->token_ids[next]) ); } AstNode *res = ast_create_node(pc, NodeTypeFnProto, first); res->data.fn_proto = {}; - res->data.fn_proto.name = token_buf(identifier); + res->data.fn_proto.name = token_buf(pc, identifier); res->data.fn_proto.params = params; res->data.fn_proto.align_expr = align_expr; res->data.fn_proto.section_expr = section_expr; res->data.fn_proto.callconv_expr = callconv_expr; - res->data.fn_proto.auto_err_set = exmark != nullptr; + res->data.fn_proto.auto_err_set = exmark != 0; res->data.fn_proto.return_type = return_type; for (size_t i = 0; i < params.length; i++) { @@ -869,28 +825,28 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc) { // VarDecl <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? LinkSection? (EQUAL Expr)? SEMICOLON static AstNode *ast_parse_var_decl(ParseContext *pc) { - Token *mut_kw = eat_token_if(pc, TokenIdKeywordConst); - if (mut_kw == nullptr) + TokenIndex mut_kw = eat_token_if(pc, TokenIdKeywordConst); + if (mut_kw == 0) mut_kw = eat_token_if(pc, TokenIdKeywordVar); - if (mut_kw == nullptr) + if (mut_kw == 0) return nullptr; - Token *identifier = expect_token(pc, TokenIdSymbol); + TokenIndex identifier = expect_token(pc, TokenIdIdentifier); AstNode *type_expr = nullptr; - if (eat_token_if(pc, TokenIdColon) != nullptr) + if (eat_token_if(pc, TokenIdColon) != 0) type_expr = ast_expect(pc, ast_parse_type_expr); AstNode *align_expr = ast_parse_byte_align(pc); AstNode *section_expr = ast_parse_link_section(pc); AstNode *expr = nullptr; - if (eat_token_if(pc, TokenIdEq) != nullptr) + if (eat_token_if(pc, TokenIdEq) != 0) expr = ast_expect(pc, ast_parse_expr); expect_token(pc, TokenIdSemicolon); AstNode *res = ast_create_node(pc, NodeTypeVariableDeclaration, mut_kw); - res->data.variable_declaration.is_const = mut_kw->id == TokenIdKeywordConst; - res->data.variable_declaration.symbol = token_buf(identifier); + res->data.variable_declaration.is_const = pc->token_ids[mut_kw] == TokenIdKeywordConst; + res->data.variable_declaration.symbol = token_buf(pc, identifier); res->data.variable_declaration.type = type_expr; res->data.variable_declaration.align_expr = align_expr; res->data.variable_declaration.section_expr = section_expr; @@ -900,14 +856,14 @@ static AstNode *ast_parse_var_decl(ParseContext *pc) { // ContainerField <- KEYWORD_comptime? IDENTIFIER (COLON TypeExpr ByteAlign?)? (EQUAL Expr)? static AstNode *ast_parse_container_field(ParseContext *pc) { - Token *identifier = eat_token_if(pc, TokenIdSymbol); - if (identifier == nullptr) + TokenIndex identifier = eat_token_if(pc, TokenIdIdentifier); + if (identifier == 0) return nullptr; AstNode *type_expr = nullptr; - if (eat_token_if(pc, TokenIdColon) != nullptr) { - Token *anytype_tok = eat_token_if(pc, TokenIdKeywordAnyType); - if (anytype_tok != nullptr) { + if (eat_token_if(pc, TokenIdColon) != 0) { + TokenIndex anytype_tok = eat_token_if(pc, TokenIdKeywordAnyType); + if (anytype_tok != 0) { type_expr = ast_create_node(pc, NodeTypeAnyTypeField, anytype_tok); } else { type_expr = ast_expect(pc, ast_parse_type_expr); @@ -915,11 +871,11 @@ static AstNode *ast_parse_container_field(ParseContext *pc) { } AstNode *align_expr = ast_parse_byte_align(pc); AstNode *expr = nullptr; - if (eat_token_if(pc, TokenIdEq) != nullptr) + if (eat_token_if(pc, TokenIdEq) != 0) expr = ast_expect(pc, ast_parse_expr); AstNode *res = ast_create_node(pc, NodeTypeStructField, identifier); - res->data.struct_field.name = token_buf(identifier); + res->data.struct_field.name = token_buf(pc, identifier); res->data.struct_field.type = type_expr; res->data.struct_field.value = expr; res->data.struct_field.align_expr = align_expr; @@ -938,52 +894,52 @@ static AstNode *ast_parse_container_field(ParseContext *pc) { // / SwitchExpr // / AssignExpr SEMICOLON static AstNode *ast_parse_statement(ParseContext *pc) { - Token *comptime = eat_token_if(pc, TokenIdKeywordCompTime); + TokenIndex comptime = eat_token_if(pc, TokenIdKeywordCompTime); AstNode *var_decl = ast_parse_var_decl(pc); if (var_decl != nullptr) { assert(var_decl->type == NodeTypeVariableDeclaration); - var_decl->data.variable_declaration.is_comptime = comptime != nullptr; + var_decl->data.variable_declaration.is_comptime = comptime != 0; return var_decl; } - if (comptime != nullptr) { + if (comptime != 0) { AstNode *statement = ast_expect(pc, ast_parse_block_expr_statement); AstNode *res = ast_create_node(pc, NodeTypeCompTime, comptime); res->data.comptime_expr.expr = statement; return res; } - Token *nosuspend = eat_token_if(pc, TokenIdKeywordNoSuspend); - if (nosuspend != nullptr) { + TokenIndex nosuspend = eat_token_if(pc, TokenIdKeywordNoSuspend); + if (nosuspend != 0) { AstNode *statement = ast_expect(pc, ast_parse_block_expr_statement); AstNode *res = ast_create_node(pc, NodeTypeNoSuspend, nosuspend); res->data.nosuspend_expr.expr = statement; return res; } - Token *suspend = eat_token_if(pc, TokenIdKeywordSuspend); - if (suspend != nullptr) { + TokenIndex suspend = eat_token_if(pc, TokenIdKeywordSuspend); + if (suspend != 0) { AstNode *statement = ast_expect(pc, ast_parse_block_expr_statement); AstNode *res = ast_create_node(pc, NodeTypeSuspend, suspend); res->data.suspend.block = statement; return res; } - Token *defer = eat_token_if(pc, TokenIdKeywordDefer); - if (defer == nullptr) + TokenIndex defer = eat_token_if(pc, TokenIdKeywordDefer); + if (defer == 0) defer = eat_token_if(pc, TokenIdKeywordErrdefer); - if (defer != nullptr) { - Token *payload = (defer->id == TokenIdKeywordErrdefer) ? - ast_parse_payload(pc) : nullptr; + if (defer != 0) { + TokenIndex payload = (pc->token_ids[defer] == TokenIdKeywordErrdefer) ? + ast_parse_payload(pc) : 0; AstNode *statement = ast_expect(pc, ast_parse_block_expr_statement); AstNode *res = ast_create_node(pc, NodeTypeDefer, defer); res->data.defer.kind = ReturnKindUnconditional; res->data.defer.expr = statement; - if (defer->id == TokenIdKeywordErrdefer) { + if (pc->token_ids[defer] == TokenIdKeywordErrdefer) { res->data.defer.kind = ReturnKindError; - if (payload != nullptr) - res->data.defer.err_payload = token_symbol(pc, payload); + if (payload != 0) + res->data.defer.err_payload = token_identifier(pc, payload); } return res; } @@ -1025,13 +981,13 @@ static AstNode *ast_parse_if_statement(ParseContext *pc) { } if (body == nullptr) { - Token *tok = eat_token(pc); - ast_error(pc, tok, "expected if body, found '%s'", token_name(tok->id)); + TokenIndex tok = eat_token(pc); + ast_error(pc, tok, "expected if body, found '%s'", token_name(pc->token_ids[tok])); } - Token *err_payload = nullptr; + TokenIndex err_payload = 0; AstNode *else_body = nullptr; - if (eat_token_if(pc, TokenIdKeywordElse) != nullptr) { + if (eat_token_if(pc, TokenIdKeywordElse) != 0) { err_payload = ast_parse_payload(pc); else_body = ast_expect(pc, ast_parse_statement); } @@ -1040,14 +996,14 @@ static AstNode *ast_parse_if_statement(ParseContext *pc) { expect_token(pc, TokenIdSemicolon); assert(res->type == NodeTypeIfOptional); - if (err_payload != nullptr) { + if (err_payload != 0) { AstNodeTestExpr old = res->data.test_expr; res->type = NodeTypeIfErrorExpr; res->data.if_err_expr.target_node = old.target_node; res->data.if_err_expr.var_is_ptr = old.var_is_ptr; res->data.if_err_expr.var_symbol = old.var_symbol; res->data.if_err_expr.then_node = body; - res->data.if_err_expr.err_symbol = token_buf(err_payload); + res->data.if_err_expr.err_symbol = token_buf(pc, err_payload); res->data.if_err_expr.else_node = else_body; return res; } @@ -1068,11 +1024,11 @@ static AstNode *ast_parse_if_statement(ParseContext *pc) { // LabeledStatement <- BlockLabel? (Block / LoopStatement) static AstNode *ast_parse_labeled_statement(ParseContext *pc) { - Token *label = ast_parse_block_label(pc); + TokenIndex label = ast_parse_block_label(pc); AstNode *block = ast_parse_block(pc); if (block != nullptr) { assert(block->type == NodeTypeBlock); - block->data.block.name = token_buf(label); + block->data.block.name = token_buf(pc, label); return block; } @@ -1080,10 +1036,10 @@ static AstNode *ast_parse_labeled_statement(ParseContext *pc) { if (loop != nullptr) { switch (loop->type) { case NodeTypeForExpr: - loop->data.for_expr.name = token_buf(label); + loop->data.for_expr.name = token_buf(pc, label); break; case NodeTypeWhileExpr: - loop->data.while_expr.name = token_buf(label); + loop->data.while_expr.name = token_buf(pc, label); break; default: zig_unreachable(); @@ -1091,29 +1047,29 @@ static AstNode *ast_parse_labeled_statement(ParseContext *pc) { return loop; } - if (label != nullptr) + if (label != 0) ast_invalid_token_error(pc, peek_token(pc)); return nullptr; } // LoopStatement <- KEYWORD_inline? (ForStatement / WhileStatement) static AstNode *ast_parse_loop_statement(ParseContext *pc) { - Token *inline_token = eat_token_if(pc, TokenIdKeywordInline); + TokenIndex inline_token = eat_token_if(pc, TokenIdKeywordInline); AstNode *for_statement = ast_parse_for_statement(pc); if (for_statement != nullptr) { assert(for_statement->type == NodeTypeForExpr); - for_statement->data.for_expr.is_inline = inline_token != nullptr; + for_statement->data.for_expr.is_inline = inline_token != 0; return for_statement; } AstNode *while_statement = ast_parse_while_statement(pc); if (while_statement != nullptr) { assert(while_statement->type == NodeTypeWhileExpr); - while_statement->data.while_expr.is_inline = inline_token != nullptr; + while_statement->data.while_expr.is_inline = inline_token != 0; return while_statement; } - if (inline_token != nullptr) + if (inline_token != 0) ast_invalid_token_error(pc, peek_token(pc)); return nullptr; } @@ -1134,12 +1090,12 @@ static AstNode *ast_parse_for_statement(ParseContext *pc) { } if (body == nullptr) { - Token *tok = eat_token(pc); - ast_error(pc, tok, "expected loop body, found '%s'", token_name(tok->id)); + TokenIndex tok = eat_token(pc); + ast_error(pc, tok, "expected loop body, found '%s'", token_name(pc->token_ids[tok])); } AstNode *else_body = nullptr; - if (eat_token_if(pc, TokenIdKeywordElse) != nullptr) { + if (eat_token_if(pc, TokenIdKeywordElse) != 0) { else_body = ast_expect(pc, ast_parse_statement); } @@ -1168,13 +1124,13 @@ static AstNode *ast_parse_while_statement(ParseContext *pc) { } if (body == nullptr) { - Token *tok = eat_token(pc); - ast_error(pc, tok, "expected loop body, found '%s'", token_name(tok->id)); + TokenIndex tok = eat_token(pc); + ast_error(pc, tok, "expected loop body, found '%s'", token_name(pc->token_ids[tok])); } - Token *err_payload = nullptr; + TokenIndex err_payload = 0; AstNode *else_body = nullptr; - if (eat_token_if(pc, TokenIdKeywordElse) != nullptr) { + if (eat_token_if(pc, TokenIdKeywordElse) != 0) { err_payload = ast_parse_payload(pc); else_body = ast_expect(pc, ast_parse_statement); } @@ -1184,7 +1140,7 @@ static AstNode *ast_parse_while_statement(ParseContext *pc) { assert(res->type == NodeTypeWhileExpr); res->data.while_expr.body = body; - res->data.while_expr.err_symbol = token_buf(err_payload); + res->data.while_expr.err_symbol = token_buf(pc, err_payload); res->data.while_expr.else_node = else_body; return res; } @@ -1209,11 +1165,11 @@ static AstNode *ast_parse_block_expr_statement(ParseContext *pc) { // BlockExpr <- BlockLabel? Block static AstNode *ast_parse_block_expr(ParseContext *pc) { - Token *label = ast_parse_block_label(pc); - if (label != nullptr) { + TokenIndex label = ast_parse_block_label(pc); + if (label != 0) { AstNode *res = ast_expect(pc, ast_parse_block); assert(res->type == NodeTypeBlock); - res->data.block.name = token_buf(label); + res->data.block.name = token_buf(pc, label); return res; } @@ -1230,8 +1186,8 @@ static AstNode *ast_parse_expr(ParseContext *pc) { return ast_parse_prefix_op_expr( pc, [](ParseContext *context) { - Token *try_token = eat_token_if(context, TokenIdKeywordTry); - if (try_token != nullptr) { + TokenIndex try_token = eat_token_if(context, TokenIdKeywordTry); + if (try_token != 0) { AstNode *res = ast_create_node(context, NodeTypeReturnExpr, try_token); res->data.return_expr.kind = ReturnKindError; return res; @@ -1318,72 +1274,72 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc) { if (if_expr != nullptr) return if_expr; - Token *break_token = eat_token_if(pc, TokenIdKeywordBreak); - if (break_token != nullptr) { - Token *label = ast_parse_break_label(pc); + TokenIndex break_token = eat_token_if(pc, TokenIdKeywordBreak); + if (break_token != 0) { + TokenIndex label = ast_parse_break_label(pc); AstNode *expr = ast_parse_expr(pc); AstNode *res = ast_create_node(pc, NodeTypeBreak, break_token); - res->data.break_expr.name = token_buf(label); + res->data.break_expr.name = token_buf(pc, label); res->data.break_expr.expr = expr; return res; } - Token *comptime = eat_token_if(pc, TokenIdKeywordCompTime); - if (comptime != nullptr) { + TokenIndex comptime = eat_token_if(pc, TokenIdKeywordCompTime); + if (comptime != 0) { AstNode *expr = ast_expect(pc, ast_parse_expr); AstNode *res = ast_create_node(pc, NodeTypeCompTime, comptime); res->data.comptime_expr.expr = expr; return res; } - Token *nosuspend = eat_token_if(pc, TokenIdKeywordNoSuspend); - if (nosuspend != nullptr) { + TokenIndex nosuspend = eat_token_if(pc, TokenIdKeywordNoSuspend); + if (nosuspend != 0) { AstNode *expr = ast_expect(pc, ast_parse_expr); AstNode *res = ast_create_node(pc, NodeTypeNoSuspend, nosuspend); res->data.nosuspend_expr.expr = expr; return res; } - Token *continue_token = eat_token_if(pc, TokenIdKeywordContinue); - if (continue_token != nullptr) { - Token *label = ast_parse_break_label(pc); + TokenIndex continue_token = eat_token_if(pc, TokenIdKeywordContinue); + if (continue_token != 0) { + TokenIndex label = ast_parse_break_label(pc); AstNode *res = ast_create_node(pc, NodeTypeContinue, continue_token); - res->data.continue_expr.name = token_buf(label); + res->data.continue_expr.name = token_buf(pc, label); return res; } - Token *resume = eat_token_if(pc, TokenIdKeywordResume); - if (resume != nullptr) { + TokenIndex resume = eat_token_if(pc, TokenIdKeywordResume); + if (resume != 0) { AstNode *expr = ast_expect(pc, ast_parse_expr); AstNode *res = ast_create_node(pc, NodeTypeResume, resume); res->data.resume_expr.expr = expr; return res; } - Token *return_token = eat_token_if(pc, TokenIdKeywordReturn); - if (return_token != nullptr) { + TokenIndex return_token = eat_token_if(pc, TokenIdKeywordReturn); + if (return_token != 0) { AstNode *expr = ast_parse_expr(pc); AstNode *res = ast_create_node(pc, NodeTypeReturnExpr, return_token); res->data.return_expr.expr = expr; return res; } - Token *label = ast_parse_block_label(pc); + TokenIndex label = ast_parse_block_label(pc); AstNode *loop = ast_parse_loop_expr(pc); if (loop != nullptr) { switch (loop->type) { case NodeTypeForExpr: - loop->data.for_expr.name = token_buf(label); + loop->data.for_expr.name = token_buf(pc, label); break; case NodeTypeWhileExpr: - loop->data.while_expr.name = token_buf(label); + loop->data.while_expr.name = token_buf(pc, label); break; default: zig_unreachable(); } return loop; - } else if (label != nullptr) { + } else if (label != 0) { // Restore the tokens that we eaten by ast_parse_block_label. put_back_token(pc); put_back_token(pc); @@ -1407,8 +1363,8 @@ static AstNode *ast_parse_if_expr(ParseContext *pc) { // Block <- LBRACE Statement* RBRACE static AstNode *ast_parse_block(ParseContext *pc) { - Token *lbrace = eat_token_if(pc, TokenIdLBrace); - if (lbrace == nullptr) + TokenIndex lbrace = eat_token_if(pc, TokenIdLBrace); + if (lbrace == 0) return nullptr; ZigList statements = {}; @@ -1462,8 +1418,8 @@ static AstNode *ast_parse_curly_suffix_expr(ParseContext *pc) { // / LBRACE Expr (COMMA Expr)* COMMA? RBRACE // / LBRACE RBRACE static AstNode *ast_parse_init_list(ParseContext *pc) { - Token *lbrace = eat_token_if(pc, TokenIdLBrace); - if (lbrace == nullptr) + TokenIndex lbrace = eat_token_if(pc, TokenIdLBrace); + if (lbrace == 0) return nullptr; AstNode *first = ast_parse_field_init(pc); @@ -1472,7 +1428,7 @@ static AstNode *ast_parse_init_list(ParseContext *pc) { res->data.container_init_expr.kind = ContainerInitKindStruct; res->data.container_init_expr.entries.append(first); - while (eat_token_if(pc, TokenIdComma) != nullptr) { + while (eat_token_if(pc, TokenIdComma) != 0) { AstNode *field_init = ast_parse_field_init(pc); if (field_init == nullptr) break; @@ -1490,7 +1446,7 @@ static AstNode *ast_parse_init_list(ParseContext *pc) { if (first != nullptr) { res->data.container_init_expr.entries.append(first); - while (eat_token_if(pc, TokenIdComma) != nullptr) { + while (eat_token_if(pc, TokenIdComma) != 0) { AstNode *expr = ast_parse_expr(pc); if (expr == nullptr) break; @@ -1535,7 +1491,7 @@ static AstNode *ast_parse_error_union_expr(ParseContext *pc) { // <- KEYWORD_async PrimaryTypeExpr SuffixOp* FnCallArguments // / PrimaryTypeExpr (SuffixOp / FnCallArguments)* static AstNode *ast_parse_suffix_expr(ParseContext *pc) { - Token *async_token = eat_token_if(pc, TokenIdKeywordAsync); + TokenIndex async_token = eat_token_if(pc, TokenIdKeywordAsync); if (async_token) { AstNode *child = ast_expect(pc, ast_parse_primary_type_expr); while (true) { @@ -1652,43 +1608,21 @@ static AstNode *ast_parse_suffix_expr(ParseContext *pc) { // / STRINGLITERAL // / SwitchExpr static AstNode *ast_parse_primary_type_expr(ParseContext *pc) { - // TODO: This is not in line with the grammar. - // Because the prev stage 1 tokenizer does not parse - // @[a-zA-Z_][a-zA-Z0-9_] as one token, it has to do a - // hack, where it accepts '@' (IDENTIFIER / KEYWORD_export / - // KEYWORD_extern). - // I'd say that it's better if '@' is part of the builtin - // identifier token. - Token *at_sign = eat_token_if(pc, TokenIdAtSign); - if (at_sign != nullptr) { - Buf *name; - Token *token; - if ((token = eat_token_if(pc, TokenIdKeywordExport)) != nullptr) { - name = buf_create_from_str("export"); - } else if ((token = eat_token_if(pc, TokenIdKeywordExtern)) != nullptr) { - name = buf_create_from_str("extern"); - } else { - token = expect_token(pc, TokenIdSymbol); - name = token_buf(token); - } - + TokenIndex builtin_tok = eat_token_if(pc, TokenIdBuiltin); + if (builtin_tok != 0) { AstNode *res = ast_expect(pc, ast_parse_fn_call_arguments); - AstNode *name_sym = ast_create_node(pc, NodeTypeSymbol, token); - name_sym->data.symbol_expr.symbol = name; + AstNode *name_sym = ast_create_node(pc, NodeTypeIdentifier, builtin_tok); assert(res->type == NodeTypeFnCallExpr); - res->line = at_sign->start_line; - res->column = at_sign->start_column; + res->main_token = builtin_tok; res->data.fn_call_expr.fn_ref_expr = name_sym; res->data.fn_call_expr.modifier = CallModifierBuiltin; return res; } - Token *char_lit = eat_token_if(pc, TokenIdCharLiteral); - if (char_lit != nullptr) { - AstNode *res = ast_create_node(pc, NodeTypeCharLiteral, char_lit); - res->data.char_literal.value = char_lit->data.char_lit.c; - return res; + TokenIndex char_lit = eat_token_if(pc, TokenIdCharLiteral); + if (char_lit != 0) { + return ast_create_node(pc, NodeTypeCharLiteral, char_lit); } AstNode *container_decl = ast_parse_container_decl(pc); @@ -1703,12 +1637,9 @@ static AstNode *ast_parse_primary_type_expr(ParseContext *pc) { if (error_set_decl != nullptr) return error_set_decl; - Token *float_lit = eat_token_if(pc, TokenIdFloatLiteral); - if (float_lit != nullptr) { - AstNode *res = ast_create_node(pc, NodeTypeFloatLiteral, float_lit); - res->data.float_literal.bigfloat = &float_lit->data.float_lit.bigfloat; - res->data.float_literal.overflow = float_lit->data.float_lit.overflow; - return res; + TokenIndex float_lit = eat_token_if(pc, TokenIdFloatLiteral); + if (float_lit != 0) { + return ast_create_node(pc, NodeTypeFloatLiteral, float_lit); } AstNode *fn_proto = ast_parse_fn_proto(pc); @@ -1723,86 +1654,77 @@ static AstNode *ast_parse_primary_type_expr(ParseContext *pc) { if (labeled_type_expr != nullptr) return labeled_type_expr; - Token *identifier = eat_token_if(pc, TokenIdSymbol); - if (identifier != nullptr) - return token_symbol(pc, identifier); + TokenIndex identifier = eat_token_if(pc, TokenIdIdentifier); + if (identifier != 0) + return token_identifier(pc, identifier); AstNode *if_type_expr = ast_parse_if_type_expr(pc); if (if_type_expr != nullptr) return if_type_expr; - Token *int_lit = eat_token_if(pc, TokenIdIntLiteral); - if (int_lit != nullptr) { - AstNode *res = ast_create_node(pc, NodeTypeIntLiteral, int_lit); - res->data.int_literal.bigint = &int_lit->data.int_lit.bigint; - return res; + TokenIndex int_lit = eat_token_if(pc, TokenIdIntLiteral); + if (int_lit != 0) { + return ast_create_node(pc, NodeTypeIntLiteral, int_lit); } - Token *comptime = eat_token_if(pc, TokenIdKeywordCompTime); - if (comptime != nullptr) { + TokenIndex comptime = eat_token_if(pc, TokenIdKeywordCompTime); + if (comptime != 0) { AstNode *expr = ast_expect(pc, ast_parse_type_expr); AstNode *res = ast_create_node(pc, NodeTypeCompTime, comptime); res->data.comptime_expr.expr = expr; return res; } - Token *error = eat_token_if(pc, TokenIdKeywordError); - if (error != nullptr) { - Token *dot = expect_token(pc, TokenIdDot); - Token *name = expect_token(pc, TokenIdSymbol); + TokenIndex error = eat_token_if(pc, TokenIdKeywordError); + if (error != 0) { + TokenIndex dot = expect_token(pc, TokenIdDot); + TokenIndex name = expect_token(pc, TokenIdIdentifier); AstNode *left = ast_create_node(pc, NodeTypeErrorType, error); AstNode *res = ast_create_node(pc, NodeTypeFieldAccessExpr, dot); res->data.field_access_expr.struct_expr = left; - res->data.field_access_expr.field_name = token_buf(name); + res->data.field_access_expr.field_name = token_buf(pc, name); return res; } - Token *false_token = eat_token_if(pc, TokenIdKeywordFalse); - if (false_token != nullptr) { + TokenIndex false_token = eat_token_if(pc, TokenIdKeywordFalse); + if (false_token != 0) { AstNode *res = ast_create_node(pc, NodeTypeBoolLiteral, false_token); res->data.bool_literal.value = false; return res; } - Token *null = eat_token_if(pc, TokenIdKeywordNull); - if (null != nullptr) + TokenIndex null = eat_token_if(pc, TokenIdKeywordNull); + if (null != 0) return ast_create_node(pc, NodeTypeNullLiteral, null); - Token *anyframe = eat_token_if(pc, TokenIdKeywordAnyFrame); - if (anyframe != nullptr) + TokenIndex anyframe = eat_token_if(pc, TokenIdKeywordAnyFrame); + if (anyframe != 0) return ast_create_node(pc, NodeTypeAnyFrameType, anyframe); - Token *true_token = eat_token_if(pc, TokenIdKeywordTrue); - if (true_token != nullptr) { + TokenIndex true_token = eat_token_if(pc, TokenIdKeywordTrue); + if (true_token != 0) { AstNode *res = ast_create_node(pc, NodeTypeBoolLiteral, true_token); res->data.bool_literal.value = true; return res; } - Token *undefined = eat_token_if(pc, TokenIdKeywordUndefined); - if (undefined != nullptr) + TokenIndex undefined = eat_token_if(pc, TokenIdKeywordUndefined); + if (undefined != 0) return ast_create_node(pc, NodeTypeUndefinedLiteral, undefined); - Token *unreachable = eat_token_if(pc, TokenIdKeywordUnreachable); - if (unreachable != nullptr) + TokenIndex unreachable = eat_token_if(pc, TokenIdKeywordUnreachable); + if (unreachable != 0) return ast_create_node(pc, NodeTypeUnreachable, unreachable); - Buf *string_buf; - Token *string_lit = eat_token_if(pc, TokenIdStringLiteral); - if (string_lit != nullptr) { - string_buf = token_buf(string_lit); - } else { - Buf multiline_string_buf = BUF_INIT; - string_lit = ast_parse_multiline_string_literal(pc, &multiline_string_buf); - if (string_lit != nullptr) { - string_buf = buf_create_from_buf(&multiline_string_buf); - } + TokenIndex string_lit = eat_token_if(pc, TokenIdStringLiteral); + if (string_lit != 0) { + return ast_create_node(pc, NodeTypeStringLiteral, string_lit); } - if (string_lit != nullptr) { - AstNode *res = ast_create_node(pc, NodeTypeStringLiteral, string_lit); - res->data.string_literal.buf = string_buf; - return res; + + TokenIndex multiline_str_lit = ast_parse_multi_tok(pc, TokenIdMultilineStringLiteralLine); + if (multiline_str_lit != 0) { + return ast_create_node(pc, NodeTypeStringLiteral, multiline_str_lit); } AstNode *switch_expr = ast_parse_switch_expr(pc); @@ -1814,22 +1736,21 @@ static AstNode *ast_parse_primary_type_expr(ParseContext *pc) { // ContainerDecl <- (KEYWORD_extern / KEYWORD_packed)? ContainerDeclAuto static AstNode *ast_parse_container_decl(ParseContext *pc) { - Token *layout_token = eat_token_if(pc, TokenIdKeywordExtern); - if (layout_token == nullptr) + TokenIndex layout_token = eat_token_if(pc, TokenIdKeywordExtern); + if (layout_token == 0) layout_token = eat_token_if(pc, TokenIdKeywordPacked); AstNode *res = ast_parse_container_decl_auto(pc); if (res == nullptr) { - if (layout_token != nullptr) + if (layout_token != 0) put_back_token(pc); return nullptr; } assert(res->type == NodeTypeContainerDecl); - if (layout_token != nullptr) { - res->line = layout_token->start_line; - res->column = layout_token->start_column; - res->data.container_decl.layout = layout_token->id == TokenIdKeywordExtern + if (layout_token != 0) { + res->main_token = layout_token; + res->data.container_decl.layout = pc->token_ids[layout_token] == TokenIdKeywordExtern ? ContainerLayoutExtern : ContainerLayoutPacked; } @@ -1838,28 +1759,27 @@ static AstNode *ast_parse_container_decl(ParseContext *pc) { // ErrorSetDecl <- KEYWORD_error LBRACE IdentifierList RBRACE static AstNode *ast_parse_error_set_decl(ParseContext *pc) { - Token *first = eat_token_if(pc, TokenIdKeywordError); - if (first == nullptr) + TokenIndex first = eat_token_if(pc, TokenIdKeywordError); + if (first == 0) return nullptr; - if (eat_token_if(pc, TokenIdLBrace) == nullptr) { + if (eat_token_if(pc, TokenIdLBrace) == 0) { put_back_token(pc); return nullptr; } ZigList decls = ast_parse_list(pc, TokenIdComma, [](ParseContext *context) { - Buf doc_comment_buf = BUF_INIT; - Token *doc_token = ast_parse_doc_comments(context, &doc_comment_buf); - Token *ident = eat_token_if(context, TokenIdSymbol); - if (ident == nullptr) + TokenIndex doc_token = ast_parse_doc_comments(context); + TokenIndex ident = eat_token_if(context, TokenIdIdentifier); + if (ident == 0) return (AstNode*)nullptr; - AstNode *symbol_node = token_symbol(context, ident); - if (doc_token == nullptr) + AstNode *symbol_node = token_identifier(context, ident); + if (doc_token == 0) return symbol_node; AstNode *field_node = ast_create_node(context, NodeTypeErrorSetField, doc_token); field_node->data.err_set_field.field_name = symbol_node; - field_node->data.err_set_field.doc_comments = doc_comment_buf; + field_node->data.err_set_field.doc_comments = doc_token; return field_node; }); expect_token(pc, TokenIdRBrace); @@ -1871,8 +1791,8 @@ static AstNode *ast_parse_error_set_decl(ParseContext *pc) { // GroupedExpr <- LPAREN Expr RPAREN static AstNode *ast_parse_grouped_expr(ParseContext *pc) { - Token *lparen = eat_token_if(pc, TokenIdLParen); - if (lparen == nullptr) + TokenIndex lparen = eat_token_if(pc, TokenIdLParen); + if (lparen == 0) return nullptr; AstNode *expr = ast_expect(pc, ast_parse_expr); @@ -1892,12 +1812,12 @@ static AstNode *ast_parse_if_type_expr(ParseContext *pc) { // <- BlockLabel Block // / BlockLabel? LoopTypeExpr static AstNode *ast_parse_labeled_type_expr(ParseContext *pc) { - Token *label = ast_parse_block_label(pc); - if (label != nullptr) { + TokenIndex label = ast_parse_block_label(pc); + if (label != 0) { AstNode *block = ast_parse_block(pc); if (block != nullptr) { assert(block->type == NodeTypeBlock); - block->data.block.name = token_buf(label); + block->data.block.name = token_buf(pc, label); return block; } } @@ -1906,10 +1826,10 @@ static AstNode *ast_parse_labeled_type_expr(ParseContext *pc) { if (loop != nullptr) { switch (loop->type) { case NodeTypeForExpr: - loop->data.for_expr.name = token_buf(label); + loop->data.for_expr.name = token_buf(pc, label); break; case NodeTypeWhileExpr: - loop->data.while_expr.name = token_buf(label); + loop->data.while_expr.name = token_buf(pc, label); break; default: zig_unreachable(); @@ -1917,7 +1837,7 @@ static AstNode *ast_parse_labeled_type_expr(ParseContext *pc) { return loop; } - if (label != nullptr) { + if (label != 0) { put_back_token(pc); put_back_token(pc); } @@ -1945,8 +1865,8 @@ static AstNode *ast_parse_while_type_expr(ParseContext *pc) { // SwitchExpr <- KEYWORD_switch LPAREN Expr RPAREN LBRACE SwitchProngList RBRACE static AstNode *ast_parse_switch_expr(ParseContext *pc) { - Token *switch_token = eat_token_if(pc, TokenIdKeywordSwitch); - if (switch_token == nullptr) + TokenIndex switch_token = eat_token_if(pc, TokenIdKeywordSwitch); + if (switch_token == 0) return nullptr; expect_token(pc, TokenIdLParen); @@ -1964,11 +1884,11 @@ static AstNode *ast_parse_switch_expr(ParseContext *pc) { // AsmExpr <- KEYWORD_asm KEYWORD_volatile? LPAREN STRINGLITERAL AsmOutput? RPAREN static AstNode *ast_parse_asm_expr(ParseContext *pc) { - Token *asm_token = eat_token_if(pc, TokenIdKeywordAsm); - if (asm_token == nullptr) + TokenIndex asm_token = eat_token_if(pc, TokenIdKeywordAsm); + if (asm_token == 0) return nullptr; - Token *volatile_token = eat_token_if(pc, TokenIdKeywordVolatile); + TokenIndex volatile_token = eat_token_if(pc, TokenIdKeywordVolatile); expect_token(pc, TokenIdLParen); AstNode *asm_template = ast_expect(pc, ast_parse_expr); AstNode *res = ast_parse_asm_output(pc); @@ -1976,25 +1896,21 @@ static AstNode *ast_parse_asm_expr(ParseContext *pc) { res = ast_create_node_no_line_info(pc, NodeTypeAsmExpr); expect_token(pc, TokenIdRParen); - res->line = asm_token->start_line; - res->column = asm_token->start_column; + res->main_token = asm_token; res->data.asm_expr.volatile_token = volatile_token; res->data.asm_expr.asm_template = asm_template; return res; } static AstNode *ast_parse_anon_lit(ParseContext *pc) { - Token *period = eat_token_if(pc, TokenIdDot); - if (period == nullptr) + TokenIndex period = eat_token_if(pc, TokenIdDot); + if (period == 0) return nullptr; // anon enum literal - Token *identifier = eat_token_if(pc, TokenIdSymbol); - if (identifier != nullptr) { - AstNode *res = ast_create_node(pc, NodeTypeEnumLiteral, period); - res->data.enum_literal.period = period; - res->data.enum_literal.identifier = identifier; - return res; + TokenIndex identifier = eat_token_if(pc, TokenIdIdentifier); + if (identifier != 0) { + return ast_create_node(pc, NodeTypeEnumLiteral, period); } // anon container literal @@ -2007,7 +1923,7 @@ static AstNode *ast_parse_anon_lit(ParseContext *pc) { // AsmOutput <- COLON AsmOutputList AsmInput? static AstNode *ast_parse_asm_output(ParseContext *pc) { - if (eat_token_if(pc, TokenIdColon) == nullptr) + if (eat_token_if(pc, TokenIdColon) == 0) return nullptr; ZigList output_list = ast_parse_list(pc, TokenIdComma, ast_parse_asm_output_item); @@ -2021,20 +1937,20 @@ static AstNode *ast_parse_asm_output(ParseContext *pc) { // AsmOutputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN (MINUSRARROW TypeExpr / IDENTIFIER) RPAREN static AsmOutput *ast_parse_asm_output_item(ParseContext *pc) { - if (eat_token_if(pc, TokenIdLBracket) == nullptr) + if (eat_token_if(pc, TokenIdLBracket) == 0) return nullptr; - Token *sym_name = expect_token(pc, TokenIdSymbol); + TokenIndex sym_name = expect_token(pc, TokenIdIdentifier); expect_token(pc, TokenIdRBracket); - Token *str = eat_token_if(pc, TokenIdMultilineStringLiteral); - if (str == nullptr) + TokenIndex str = ast_parse_multi_tok(pc, TokenIdMultilineStringLiteralLine); + if (str == 0) str = expect_token(pc, TokenIdStringLiteral); expect_token(pc, TokenIdLParen); - Token *var_name = eat_token_if(pc, TokenIdSymbol); + TokenIndex var_name = eat_token_if(pc, TokenIdIdentifier); AstNode *return_type = nullptr; - if (var_name == nullptr) { + if (var_name == 0) { expect_token(pc, TokenIdArrow); return_type = ast_expect(pc, ast_parse_type_expr); } @@ -2042,16 +1958,16 @@ static AsmOutput *ast_parse_asm_output_item(ParseContext *pc) { expect_token(pc, TokenIdRParen); AsmOutput *res = heap::c_allocator.create(); - res->asm_symbolic_name = token_buf(sym_name); - res->constraint = token_buf(str); - res->variable_name = token_buf(var_name); + res->asm_symbolic_name = token_buf(pc, sym_name); + res->constraint = token_buf(pc, str); + res->variable_name = token_buf(pc, var_name); res->return_type = return_type; return res; } // AsmInput <- COLON AsmInputList AsmClobbers? static AstNode *ast_parse_asm_input(ParseContext *pc) { - if (eat_token_if(pc, TokenIdColon) == nullptr) + if (eat_token_if(pc, TokenIdColon) == 0) return nullptr; ZigList input_list = ast_parse_list(pc, TokenIdComma, ast_parse_asm_input_item); @@ -2065,37 +1981,35 @@ static AstNode *ast_parse_asm_input(ParseContext *pc) { // AsmInputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN Expr RPAREN static AsmInput *ast_parse_asm_input_item(ParseContext *pc) { - if (eat_token_if(pc, TokenIdLBracket) == nullptr) + if (eat_token_if(pc, TokenIdLBracket) == 0) return nullptr; - Token *sym_name = expect_token(pc, TokenIdSymbol); + TokenIndex sym_name = expect_token(pc, TokenIdIdentifier); expect_token(pc, TokenIdRBracket); - Token *constraint = eat_token_if(pc, TokenIdMultilineStringLiteral); - if (constraint == nullptr) - constraint = expect_token(pc, TokenIdStringLiteral); + TokenIndex constraint = expect_token(pc, TokenIdStringLiteral); expect_token(pc, TokenIdLParen); AstNode *expr = ast_expect(pc, ast_parse_expr); expect_token(pc, TokenIdRParen); AsmInput *res = heap::c_allocator.create(); - res->asm_symbolic_name = token_buf(sym_name); - res->constraint = token_buf(constraint); + res->asm_symbolic_name = token_buf(pc, sym_name); + res->constraint = token_buf(pc, constraint); res->expr = expr; return res; } // AsmClobbers <- COLON StringList static AstNode *ast_parse_asm_clobbers(ParseContext *pc) { - if (eat_token_if(pc, TokenIdColon) == nullptr) + if (eat_token_if(pc, TokenIdColon) == 0) return nullptr; ZigList clobber_list = ast_parse_list(pc, TokenIdComma, [](ParseContext *context) { - Token *str = eat_token_if(context, TokenIdStringLiteral); - if (str == nullptr) - str = eat_token_if(context, TokenIdMultilineStringLiteral); - if (str != nullptr) - return token_buf(str); + TokenIndex str = eat_token_if(context, TokenIdStringLiteral); + if (str == 0) + str = ast_parse_multi_tok(context, TokenIdMultilineStringLiteralLine); + if (str != 0) + return token_buf(context, str); return (Buf*)nullptr; }); @@ -2105,24 +2019,24 @@ static AstNode *ast_parse_asm_clobbers(ParseContext *pc) { } // BreakLabel <- COLON IDENTIFIER -static Token *ast_parse_break_label(ParseContext *pc) { - if (eat_token_if(pc, TokenIdColon) == nullptr) - return nullptr; +static TokenIndex ast_parse_break_label(ParseContext *pc) { + if (eat_token_if(pc, TokenIdColon) == 0) + return 0; - return expect_token(pc, TokenIdSymbol); + return expect_token(pc, TokenIdIdentifier); } // BlockLabel <- IDENTIFIER COLON -static Token *ast_parse_block_label(ParseContext *pc) { - Token *ident = eat_token_if(pc, TokenIdSymbol); - if (ident == nullptr) - return nullptr; +static TokenIndex ast_parse_block_label(ParseContext *pc) { + TokenIndex ident = eat_token_if(pc, TokenIdIdentifier); + if (ident == 0) + return 0; // We do 2 token lookahead here, as we don't want to error when // parsing identifiers. - if (eat_token_if(pc, TokenIdColon) == nullptr) { + if (eat_token_if(pc, TokenIdColon) == 0) { put_back_token(pc); - return nullptr; + return 0; } return ident; @@ -2130,17 +2044,17 @@ static Token *ast_parse_block_label(ParseContext *pc) { // FieldInit <- DOT IDENTIFIER EQUAL Expr static AstNode *ast_parse_field_init(ParseContext *pc) { - Token *first = eat_token_if(pc, TokenIdDot); - if (first == nullptr) + TokenIndex first = eat_token_if(pc, TokenIdDot); + if (first == 0) return nullptr; - Token *name = eat_token_if(pc, TokenIdSymbol); - if (name == nullptr) { + TokenIndex name = eat_token_if(pc, TokenIdIdentifier); + if (name == 0) { // Because of anon literals ".{" is also valid. put_back_token(pc); return nullptr; } - if (eat_token_if(pc, TokenIdEq) == nullptr) { + if (eat_token_if(pc, TokenIdEq) == 0) { // Because ".Name" can also be intepreted as an enum literal, we should put back // those two tokens again so that the parser can try to parse them as the enum // literal later. @@ -2151,15 +2065,15 @@ static AstNode *ast_parse_field_init(ParseContext *pc) { AstNode *expr = ast_expect(pc, ast_parse_expr); AstNode *res = ast_create_node(pc, NodeTypeStructValueField, first); - res->data.struct_val_field.name = token_buf(name); + res->data.struct_val_field.name = token_buf(pc, name); res->data.struct_val_field.expr = expr; return res; } // WhileContinueExpr <- COLON LPAREN AssignExpr RPAREN static AstNode *ast_parse_while_continue_expr(ParseContext *pc) { - Token *first = eat_token_if(pc, TokenIdColon); - if (first == nullptr) + TokenIndex first = eat_token_if(pc, TokenIdColon); + if (first == 0) return nullptr; expect_token(pc, TokenIdLParen); @@ -2170,8 +2084,8 @@ static AstNode *ast_parse_while_continue_expr(ParseContext *pc) { // LinkSection <- KEYWORD_linksection LPAREN Expr RPAREN static AstNode *ast_parse_link_section(ParseContext *pc) { - Token *first = eat_token_if(pc, TokenIdKeywordLinkSection); - if (first == nullptr) + TokenIndex first = eat_token_if(pc, TokenIdKeywordLinkSection); + if (first == 0) return nullptr; expect_token(pc, TokenIdLParen); @@ -2182,8 +2096,8 @@ static AstNode *ast_parse_link_section(ParseContext *pc) { // CallConv <- KEYWORD_callconv LPAREN Expr RPAREN static AstNode *ast_parse_callconv(ParseContext *pc) { - Token *first = eat_token_if(pc, TokenIdKeywordCallconv); - if (first == nullptr) + TokenIndex first = eat_token_if(pc, TokenIdKeywordCallconv); + if (first == 0) return nullptr; expect_token(pc, TokenIdLParen); @@ -2194,28 +2108,27 @@ static AstNode *ast_parse_callconv(ParseContext *pc) { // ParamDecl <- (KEYWORD_noalias / KEYWORD_comptime)? (IDENTIFIER COLON)? ParamType static AstNode *ast_parse_param_decl(ParseContext *pc) { - Buf doc_comments = BUF_INIT; - ast_parse_doc_comments(pc, &doc_comments); + TokenIndex first_doc_comment = ast_parse_doc_comments(pc); - Token *first = eat_token_if(pc, TokenIdKeywordNoAlias); - if (first == nullptr) + TokenIndex first = eat_token_if(pc, TokenIdKeywordNoAlias); + if (first == 0) first = eat_token_if(pc, TokenIdKeywordCompTime); - Token *name = eat_token_if(pc, TokenIdSymbol); - if (name != nullptr) { - if (eat_token_if(pc, TokenIdColon) != nullptr) { - if (first == nullptr) + TokenIndex name = eat_token_if(pc, TokenIdIdentifier); + if (name != 0) { + if (eat_token_if(pc, TokenIdColon) != 0) { + if (first == 0) first = name; } else { // We put back the ident, so it can be parsed as a ParamType // later. put_back_token(pc); - name = nullptr; + name = 0; } } AstNode *res; - if (first == nullptr) { + if (first == 0) { first = peek_token(pc); res = ast_parse_param_type(pc); } else { @@ -2226,12 +2139,11 @@ static AstNode *ast_parse_param_decl(ParseContext *pc) { return nullptr; assert(res->type == NodeTypeParamDecl); - res->line = first->start_line; - res->column = first->start_column; - res->data.param_decl.name = token_buf(name); - res->data.param_decl.doc_comments = doc_comments; - res->data.param_decl.is_noalias = first->id == TokenIdKeywordNoAlias; - res->data.param_decl.is_comptime = first->id == TokenIdKeywordCompTime; + res->main_token = first; + res->data.param_decl.name = token_buf(pc, name); + res->data.param_decl.doc_comments = first_doc_comment; + res->data.param_decl.is_noalias = pc->token_ids[first] == TokenIdKeywordNoAlias; + res->data.param_decl.is_comptime = pc->token_ids[first] == TokenIdKeywordCompTime; return res; } @@ -2240,15 +2152,15 @@ static AstNode *ast_parse_param_decl(ParseContext *pc) { // / DOT3 // / TypeExpr static AstNode *ast_parse_param_type(ParseContext *pc) { - Token *anytype_token = eat_token_if(pc, TokenIdKeywordAnyType); - if (anytype_token != nullptr) { + TokenIndex anytype_token = eat_token_if(pc, TokenIdKeywordAnyType); + if (anytype_token != 0) { AstNode *res = ast_create_node(pc, NodeTypeParamDecl, anytype_token); res->data.param_decl.anytype_token = anytype_token; return res; } - Token *dots = eat_token_if(pc, TokenIdEllipsis3); - if (dots != nullptr) { + TokenIndex dots = eat_token_if(pc, TokenIdEllipsis3); + if (dots != 0) { AstNode *res = ast_create_node(pc, NodeTypeParamDecl, dots); res->data.param_decl.is_var_args = true; return res; @@ -2266,8 +2178,8 @@ static AstNode *ast_parse_param_type(ParseContext *pc) { // IfPrefix <- KEYWORD_if LPAREN Expr RPAREN PtrPayload? static AstNode *ast_parse_if_prefix(ParseContext *pc) { - Token *first = eat_token_if(pc, TokenIdKeywordIf); - if (first == nullptr) + TokenIndex first = eat_token_if(pc, TokenIdKeywordIf); + if (first == 0) return nullptr; expect_token(pc, TokenIdLParen); @@ -2279,16 +2191,16 @@ static AstNode *ast_parse_if_prefix(ParseContext *pc) { AstNode *res = ast_create_node(pc, NodeTypeIfOptional, first); res->data.test_expr.target_node = condition; if (opt_payload.unwrap(&payload)) { - res->data.test_expr.var_symbol = token_buf(payload.payload); - res->data.test_expr.var_is_ptr = payload.asterisk != nullptr; + res->data.test_expr.var_symbol = token_buf(pc, payload.payload); + res->data.test_expr.var_is_ptr = payload.asterisk != 0; } return res; } // WhilePrefix <- KEYWORD_while LPAREN Expr RPAREN PtrPayload? WhileContinueExpr? static AstNode *ast_parse_while_prefix(ParseContext *pc) { - Token *while_token = eat_token_if(pc, TokenIdKeywordWhile); - if (while_token == nullptr) + TokenIndex while_token = eat_token_if(pc, TokenIdKeywordWhile); + if (while_token == 0) return nullptr; expect_token(pc, TokenIdLParen); @@ -2302,8 +2214,8 @@ static AstNode *ast_parse_while_prefix(ParseContext *pc) { res->data.while_expr.condition = condition; res->data.while_expr.continue_expr = continue_expr; if (opt_payload.unwrap(&payload)) { - res->data.while_expr.var_symbol = token_buf(payload.payload); - res->data.while_expr.var_is_ptr = payload.asterisk != nullptr; + res->data.while_expr.var_symbol = token_buf(pc, payload.payload); + res->data.while_expr.var_is_ptr = payload.asterisk != 0; } return res; @@ -2311,8 +2223,8 @@ static AstNode *ast_parse_while_prefix(ParseContext *pc) { // ForPrefix <- KEYWORD_for LPAREN Expr RPAREN PtrIndexPayload static AstNode *ast_parse_for_prefix(ParseContext *pc) { - Token *for_token = eat_token_if(pc, TokenIdKeywordFor); - if (for_token == nullptr) + TokenIndex for_token = eat_token_if(pc, TokenIdKeywordFor); + if (for_token == 0) return nullptr; expect_token(pc, TokenIdLParen); @@ -2324,31 +2236,31 @@ static AstNode *ast_parse_for_prefix(ParseContext *pc) { AstNode *res = ast_create_node(pc, NodeTypeForExpr, for_token); res->data.for_expr.array_expr = array_expr; - res->data.for_expr.elem_node = token_symbol(pc, payload.payload); - res->data.for_expr.elem_is_ptr = payload.asterisk != nullptr; - if (payload.index != nullptr) - res->data.for_expr.index_node = token_symbol(pc, payload.index); + res->data.for_expr.elem_node = token_identifier(pc, payload.payload); + res->data.for_expr.elem_is_ptr = payload.asterisk != 0; + if (payload.index != 0) + res->data.for_expr.index_node = token_identifier(pc, payload.index); return res; } // Payload <- PIPE IDENTIFIER PIPE -static Token *ast_parse_payload(ParseContext *pc) { - if (eat_token_if(pc, TokenIdBinOr) == nullptr) - return nullptr; +static TokenIndex ast_parse_payload(ParseContext *pc) { + if (eat_token_if(pc, TokenIdBinOr) == 0) + return 0; - Token *res = expect_token(pc, TokenIdSymbol); + TokenIndex res = expect_token(pc, TokenIdIdentifier); expect_token(pc, TokenIdBinOr); return res; } // PtrPayload <- PIPE ASTERISK? IDENTIFIER PIPE static Optional ast_parse_ptr_payload(ParseContext *pc) { - if (eat_token_if(pc, TokenIdBinOr) == nullptr) + if (eat_token_if(pc, TokenIdBinOr) == 0) return Optional::none(); - Token *asterisk = eat_token_if(pc, TokenIdStar); - Token *payload = expect_token(pc, TokenIdSymbol); + TokenIndex asterisk = eat_token_if(pc, TokenIdStar); + TokenIndex payload = expect_token(pc, TokenIdIdentifier); expect_token(pc, TokenIdBinOr); PtrPayload res; @@ -2359,14 +2271,14 @@ static Optional ast_parse_ptr_payload(ParseContext *pc) { // PtrIndexPayload <- PIPE ASTERISK? IDENTIFIER (COMMA IDENTIFIER)? PIPE static Optional ast_parse_ptr_index_payload(ParseContext *pc) { - if (eat_token_if(pc, TokenIdBinOr) == nullptr) + if (eat_token_if(pc, TokenIdBinOr) == 0) return Optional::none(); - Token *asterisk = eat_token_if(pc, TokenIdStar); - Token *payload = expect_token(pc, TokenIdSymbol); - Token *index = nullptr; - if (eat_token_if(pc, TokenIdComma) != nullptr) - index = expect_token(pc, TokenIdSymbol); + TokenIndex asterisk = eat_token_if(pc, TokenIdStar); + TokenIndex payload = expect_token(pc, TokenIdIdentifier); + TokenIndex index = 0; + if (eat_token_if(pc, TokenIdComma) != 0) + index = expect_token(pc, TokenIdIdentifier); expect_token(pc, TokenIdBinOr); PtrIndexPayload res; @@ -2390,8 +2302,8 @@ static AstNode *ast_parse_switch_prong(ParseContext *pc) { assert(res->type == NodeTypeSwitchProng); res->data.switch_prong.expr = expr; if (opt_payload.unwrap(&payload)) { - res->data.switch_prong.var_symbol = token_symbol(pc, payload.payload); - res->data.switch_prong.var_is_ptr = payload.asterisk != nullptr; + res->data.switch_prong.var_symbol = token_identifier(pc, payload.payload); + res->data.switch_prong.var_is_ptr = payload.asterisk != 0; } return res; @@ -2407,7 +2319,7 @@ static AstNode *ast_parse_switch_case(ParseContext *pc) { res->data.switch_prong.items.append(first); res->data.switch_prong.any_items_are_range = first->type == NodeTypeSwitchRange; - while (eat_token_if(pc, TokenIdComma) != nullptr) { + while (eat_token_if(pc, TokenIdComma) != 0) { AstNode *item = ast_parse_switch_item(pc); if (item == nullptr) break; @@ -2419,8 +2331,8 @@ static AstNode *ast_parse_switch_case(ParseContext *pc) { return res; } - Token *else_token = eat_token_if(pc, TokenIdKeywordElse); - if (else_token != nullptr) + TokenIndex else_token = eat_token_if(pc, TokenIdKeywordElse); + if (else_token != 0) return ast_create_node(pc, NodeTypeSwitchProng, else_token); return nullptr; @@ -2432,8 +2344,8 @@ static AstNode *ast_parse_switch_item(ParseContext *pc) { if (expr == nullptr) return nullptr; - Token *dots = eat_token_if(pc, TokenIdEllipsis3); - if (dots != nullptr) { + TokenIndex dots = eat_token_if(pc, TokenIdEllipsis3); + if (dots != 0) { AstNode *expr2 = ast_expect(pc, ast_parse_expr); AstNode *res = ast_create_node(pc, NodeTypeSwitchRange, dots); res->data.switch_range.start = expr; @@ -2478,9 +2390,9 @@ static AstNode *ast_parse_assign_op(ParseContext *pc) { table[TokenIdTimesEq] = BinOpTypeAssignTimes; table[TokenIdTimesPercentEq] = BinOpTypeAssignTimesWrap; - BinOpType op = table[peek_token(pc)->id]; + BinOpType op = table[pc->token_ids[pc->current_token]]; if (op != BinOpTypeInvalid) { - Token *op_token = eat_token(pc); + TokenIndex op_token = eat_token(pc); AstNode *res = ast_create_node(pc, NodeTypeBinOpExpr, op_token); res->data.bin_op_expr.bin_op = op; return res; @@ -2506,9 +2418,9 @@ static AstNode *ast_parse_compare_op(ParseContext *pc) { table[TokenIdCmpLessOrEq] = BinOpTypeCmpLessOrEq; table[TokenIdCmpGreaterOrEq] = BinOpTypeCmpGreaterOrEq; - BinOpType op = table[peek_token(pc)->id]; + BinOpType op = table[pc->token_ids[pc->current_token]]; if (op != BinOpTypeInvalid) { - Token *op_token = eat_token(pc); + TokenIndex op_token = eat_token(pc); AstNode *res = ast_create_node(pc, NodeTypeBinOpExpr, op_token); res->data.bin_op_expr.bin_op = op; return res; @@ -2530,20 +2442,20 @@ static AstNode *ast_parse_bitwise_op(ParseContext *pc) { table[TokenIdBinOr] = BinOpTypeBinOr; table[TokenIdKeywordOrElse] = BinOpTypeUnwrapOptional; - BinOpType op = table[peek_token(pc)->id]; + BinOpType op = table[pc->token_ids[pc->current_token]]; if (op != BinOpTypeInvalid) { - Token *op_token = eat_token(pc); + TokenIndex op_token = eat_token(pc); AstNode *res = ast_create_node(pc, NodeTypeBinOpExpr, op_token); res->data.bin_op_expr.bin_op = op; return res; } - Token *catch_token = eat_token_if(pc, TokenIdKeywordCatch); - if (catch_token != nullptr) { - Token *payload = ast_parse_payload(pc); + TokenIndex catch_token = eat_token_if(pc, TokenIdKeywordCatch); + if (catch_token != 0) { + TokenIndex payload = ast_parse_payload(pc); AstNode *res = ast_create_node(pc, NodeTypeCatchExpr, catch_token); - if (payload != nullptr) - res->data.unwrap_err_expr.symbol = token_symbol(pc, payload); + if (payload != 0) + res->data.unwrap_err_expr.symbol = token_identifier(pc, payload); return res; } @@ -2559,9 +2471,9 @@ static AstNode *ast_parse_bit_shift_op(ParseContext *pc) { table[TokenIdBitShiftLeft] = BinOpTypeBitShiftLeft; table[TokenIdBitShiftRight] = BinOpTypeBitShiftRight; - BinOpType op = table[peek_token(pc)->id]; + BinOpType op = table[pc->token_ids[pc->current_token]]; if (op != BinOpTypeInvalid) { - Token *op_token = eat_token(pc); + TokenIndex op_token = eat_token(pc); AstNode *res = ast_create_node(pc, NodeTypeBinOpExpr, op_token); res->data.bin_op_expr.bin_op = op; return res; @@ -2584,9 +2496,9 @@ static AstNode *ast_parse_addition_op(ParseContext *pc) { table[TokenIdPlusPercent] = BinOpTypeAddWrap; table[TokenIdMinusPercent] = BinOpTypeSubWrap; - BinOpType op = table[peek_token(pc)->id]; + BinOpType op = table[pc->token_ids[pc->current_token]]; if (op != BinOpTypeInvalid) { - Token *op_token = eat_token(pc); + TokenIndex op_token = eat_token(pc); AstNode *res = ast_create_node(pc, NodeTypeBinOpExpr, op_token); res->data.bin_op_expr.bin_op = op; return res; @@ -2611,9 +2523,9 @@ static AstNode *ast_parse_multiply_op(ParseContext *pc) { table[TokenIdStarStar] = BinOpTypeArrayMult; table[TokenIdTimesPercent] = BinOpTypeMultWrap; - BinOpType op = table[peek_token(pc)->id]; + BinOpType op = table[pc->token_ids[pc->current_token]]; if (op != BinOpTypeInvalid) { - Token *op_token = eat_token(pc); + TokenIndex op_token = eat_token(pc); AstNode *res = ast_create_node(pc, NodeTypeBinOpExpr, op_token); res->data.bin_op_expr.bin_op = op; return res; @@ -2638,23 +2550,23 @@ static AstNode *ast_parse_prefix_op(ParseContext *pc) { table[TokenIdMinusPercent] = PrefixOpNegationWrap; table[TokenIdAmpersand] = PrefixOpAddrOf; - PrefixOp op = table[peek_token(pc)->id]; + PrefixOp op = table[pc->token_ids[pc->current_token]]; if (op != PrefixOpInvalid) { - Token *op_token = eat_token(pc); + TokenIndex op_token = eat_token(pc); AstNode *res = ast_create_node(pc, NodeTypePrefixOpExpr, op_token); res->data.prefix_op_expr.prefix_op = op; return res; } - Token *try_token = eat_token_if(pc, TokenIdKeywordTry); - if (try_token != nullptr) { + TokenIndex try_token = eat_token_if(pc, TokenIdKeywordTry); + if (try_token != 0) { AstNode *res = ast_create_node(pc, NodeTypeReturnExpr, try_token); res->data.return_expr.kind = ReturnKindError; return res; } - Token *await = eat_token_if(pc, TokenIdKeywordAwait); - if (await != nullptr) { + TokenIndex await = eat_token_if(pc, TokenIdKeywordAwait); + if (await != 0) { AstNode *res = ast_create_node(pc, NodeTypeAwaitExpr, await); return res; } @@ -2668,16 +2580,16 @@ static AstNode *ast_parse_prefix_op(ParseContext *pc) { // / ArrayTypeStart (ByteAlign / KEYWORD_const / KEYWORD_volatile)* // / PtrTypeStart (KEYWORD_align LPAREN Expr (COLON INTEGER COLON INTEGER)? RPAREN / KEYWORD_const / KEYWORD_volatile)* static AstNode *ast_parse_prefix_type_op(ParseContext *pc) { - Token *questionmark = eat_token_if(pc, TokenIdQuestion); - if (questionmark != nullptr) { + TokenIndex questionmark = eat_token_if(pc, TokenIdQuestion); + if (questionmark != 0) { AstNode *res = ast_create_node(pc, NodeTypePrefixOpExpr, questionmark); res->data.prefix_op_expr.prefix_op = PrefixOpOptional; return res; } - Token *anyframe = eat_token_if(pc, TokenIdKeywordAnyFrame); - if (anyframe != nullptr) { - if (eat_token_if(pc, TokenIdArrow) != nullptr) { + TokenIndex anyframe = eat_token_if(pc, TokenIdKeywordAnyFrame); + if (anyframe != 0) { + if (eat_token_if(pc, TokenIdArrow) != 0) { AstNode *res = ast_create_node(pc, NodeTypeAnyFrameType, anyframe); return res; } @@ -2685,18 +2597,18 @@ static AstNode *ast_parse_prefix_type_op(ParseContext *pc) { put_back_token(pc); } - Token *arr_init_lbracket = eat_token_if(pc, TokenIdLBracket); - if (arr_init_lbracket != nullptr) { - Token *underscore = eat_token_if(pc, TokenIdSymbol); - if (underscore == nullptr) { + TokenIndex arr_init_lbracket = eat_token_if(pc, TokenIdLBracket); + if (arr_init_lbracket != 0) { + TokenIndex underscore = eat_token_if(pc, TokenIdIdentifier); + if (underscore == 0) { put_back_token(pc); - } else if (!buf_eql_str(token_buf(underscore), "_")) { + } else if (!buf_eql_str(token_buf(pc, underscore), "_")) { put_back_token(pc); put_back_token(pc); } else { AstNode *sentinel = nullptr; - Token *colon = eat_token_if(pc, TokenIdColon); - if (colon != nullptr) { + TokenIndex colon = eat_token_if(pc, TokenIdColon); + if (colon != 0) { sentinel = ast_expect(pc, ast_parse_expr); } expect_token(pc, TokenIdRBracket); @@ -2715,33 +2627,33 @@ static AstNode *ast_parse_prefix_type_op(ParseContext *pc) { if (child == nullptr) child = ptr; while (true) { - Token *allowzero_token = eat_token_if(pc, TokenIdKeywordAllowZero); - if (allowzero_token != nullptr) { + TokenIndex allowzero_token = eat_token_if(pc, TokenIdKeywordAllowZero); + if (allowzero_token != 0) { child->data.pointer_type.allow_zero_token = allowzero_token; continue; } - if (eat_token_if(pc, TokenIdKeywordAlign) != nullptr) { + if (eat_token_if(pc, TokenIdKeywordAlign) != 0) { expect_token(pc, TokenIdLParen); AstNode *align_expr = ast_expect(pc, ast_parse_expr); child->data.pointer_type.align_expr = align_expr; - if (eat_token_if(pc, TokenIdColon) != nullptr) { - Token *bit_offset_start = expect_token(pc, TokenIdIntLiteral); + if (eat_token_if(pc, TokenIdColon) != 0) { + TokenIndex bit_offset_start = expect_token(pc, TokenIdIntLiteral); expect_token(pc, TokenIdColon); - Token *host_int_bytes = expect_token(pc, TokenIdIntLiteral); - child->data.pointer_type.bit_offset_start = token_bigint(bit_offset_start); - child->data.pointer_type.host_int_bytes = token_bigint(host_int_bytes); + TokenIndex host_int_bytes = expect_token(pc, TokenIdIntLiteral); + child->data.pointer_type.bit_offset_start = bit_offset_start; + child->data.pointer_type.host_int_bytes = host_int_bytes; } expect_token(pc, TokenIdRParen); continue; } - if (eat_token_if(pc, TokenIdKeywordConst) != nullptr) { + if (eat_token_if(pc, TokenIdKeywordConst) != 0) { child->data.pointer_type.is_const = true; continue; } - if (eat_token_if(pc, TokenIdKeywordVolatile) != nullptr) { + if (eat_token_if(pc, TokenIdKeywordVolatile) != 0) { child->data.pointer_type.is_volatile = true; continue; } @@ -2756,8 +2668,8 @@ static AstNode *ast_parse_prefix_type_op(ParseContext *pc) { if (array != nullptr) { assert(array->type == NodeTypeArrayType); while (true) { - Token *allowzero_token = eat_token_if(pc, TokenIdKeywordAllowZero); - if (allowzero_token != nullptr) { + TokenIndex allowzero_token = eat_token_if(pc, TokenIdKeywordAllowZero); + if (allowzero_token != 0) { array->data.array_type.allow_zero_token = allowzero_token; continue; } @@ -2768,12 +2680,12 @@ static AstNode *ast_parse_prefix_type_op(ParseContext *pc) { continue; } - if (eat_token_if(pc, TokenIdKeywordConst) != nullptr) { + if (eat_token_if(pc, TokenIdKeywordConst) != 0) { array->data.array_type.is_const = true; continue; } - if (eat_token_if(pc, TokenIdKeywordVolatile) != nullptr) { + if (eat_token_if(pc, TokenIdKeywordVolatile) != 0) { array->data.array_type.is_volatile = true; continue; } @@ -2793,14 +2705,14 @@ static AstNode *ast_parse_prefix_type_op(ParseContext *pc) { // / DOTASTERISK // / DOTQUESTIONMARK static AstNode *ast_parse_suffix_op(ParseContext *pc) { - Token *lbracket = eat_token_if(pc, TokenIdLBracket); - if (lbracket != nullptr) { + TokenIndex lbracket = eat_token_if(pc, TokenIdLBracket); + if (lbracket != 0) { AstNode *start = ast_expect(pc, ast_parse_expr); AstNode *end = nullptr; - if (eat_token_if(pc, TokenIdEllipsis2) != nullptr) { + if (eat_token_if(pc, TokenIdEllipsis2) != 0) { AstNode *sentinel = nullptr; end = ast_parse_expr(pc); - if (eat_token_if(pc, TokenIdColon) != nullptr) { + if (eat_token_if(pc, TokenIdColon) != 0) { sentinel = ast_parse_expr(pc); } expect_token(pc, TokenIdRBracket); @@ -2819,18 +2731,18 @@ static AstNode *ast_parse_suffix_op(ParseContext *pc) { return res; } - Token *dot_asterisk = eat_token_if(pc, TokenIdDotStar); - if (dot_asterisk != nullptr) + TokenIndex dot_asterisk = eat_token_if(pc, TokenIdDotStar); + if (dot_asterisk != 0) return ast_create_node(pc, NodeTypePtrDeref, dot_asterisk); - Token *dot = eat_token_if(pc, TokenIdDot); - if (dot != nullptr) { - if (eat_token_if(pc, TokenIdQuestion) != nullptr) + TokenIndex dot = eat_token_if(pc, TokenIdDot); + if (dot != 0) { + if (eat_token_if(pc, TokenIdQuestion) != 0) return ast_create_node(pc, NodeTypeUnwrapOptional, dot); - Token *ident = expect_token(pc, TokenIdSymbol); + TokenIndex ident = expect_token(pc, TokenIdIdentifier); AstNode *res = ast_create_node(pc, NodeTypeFieldAccessExpr, dot); - res->data.field_access_expr.field_name = token_buf(ident); + res->data.field_access_expr.field_name = token_buf(pc, ident); return res; } @@ -2839,8 +2751,8 @@ static AstNode *ast_parse_suffix_op(ParseContext *pc) { // FnCallArguments <- LPAREN ExprList RPAREN static AstNode *ast_parse_fn_call_arguments(ParseContext *pc) { - Token *paren = eat_token_if(pc, TokenIdLParen); - if (paren == nullptr) + TokenIndex paren = eat_token_if(pc, TokenIdLParen); + if (paren == 0) return nullptr; ZigList params = ast_parse_list(pc, TokenIdComma, ast_parse_expr); @@ -2854,14 +2766,14 @@ static AstNode *ast_parse_fn_call_arguments(ParseContext *pc) { // ArrayTypeStart <- LBRACKET Expr? RBRACKET static AstNode *ast_parse_array_type_start(ParseContext *pc) { - Token *lbracket = eat_token_if(pc, TokenIdLBracket); - if (lbracket == nullptr) + TokenIndex lbracket = eat_token_if(pc, TokenIdLBracket); + if (lbracket == 0) return nullptr; AstNode *size = ast_parse_expr(pc); AstNode *sentinel = nullptr; - Token *colon = eat_token_if(pc, TokenIdColon); - if (colon != nullptr) { + TokenIndex colon = eat_token_if(pc, TokenIdColon); + if (colon != 0) { sentinel = ast_expect(pc, ast_parse_expr); } expect_token(pc, TokenIdRBracket); @@ -2879,10 +2791,10 @@ static AstNode *ast_parse_array_type_start(ParseContext *pc) { static AstNode *ast_parse_ptr_type_start(ParseContext *pc) { AstNode *sentinel = nullptr; - Token *asterisk = eat_token_if(pc, TokenIdStar); - if (asterisk != nullptr) { - Token *colon = eat_token_if(pc, TokenIdColon); - if (colon != nullptr) { + TokenIndex asterisk = eat_token_if(pc, TokenIdStar); + if (asterisk != 0) { + TokenIndex colon = eat_token_if(pc, TokenIdColon); + if (colon != 0) { sentinel = ast_expect(pc, ast_parse_expr); } AstNode *res = ast_create_node(pc, NodeTypePointerType, asterisk); @@ -2891,10 +2803,10 @@ static AstNode *ast_parse_ptr_type_start(ParseContext *pc) { return res; } - Token *asterisk2 = eat_token_if(pc, TokenIdStarStar); - if (asterisk2 != nullptr) { - Token *colon = eat_token_if(pc, TokenIdColon); - if (colon != nullptr) { + TokenIndex asterisk2 = eat_token_if(pc, TokenIdStarStar); + if (asterisk2 != 0) { + TokenIndex colon = eat_token_if(pc, TokenIdColon); + if (colon != 0) { sentinel = ast_expect(pc, ast_parse_expr); } AstNode *res = ast_create_node(pc, NodeTypePointerType, asterisk2); @@ -2906,15 +2818,15 @@ static AstNode *ast_parse_ptr_type_start(ParseContext *pc) { return res; } - Token *lbracket = eat_token_if(pc, TokenIdLBracket); - if (lbracket != nullptr) { - Token *star = eat_token_if(pc, TokenIdStar); - if (star == nullptr) { + TokenIndex lbracket = eat_token_if(pc, TokenIdLBracket); + if (lbracket != 0) { + TokenIndex star = eat_token_if(pc, TokenIdStar); + if (star == 0) { put_back_token(pc); } else { - Token *c_tok = eat_token_if(pc, TokenIdSymbol); - if (c_tok != nullptr) { - if (!buf_eql_str(token_buf(c_tok), "c")) { + TokenIndex c_tok = eat_token_if(pc, TokenIdIdentifier); + if (c_tok != 0) { + if (!buf_eql_str(token_buf(pc, c_tok), "c")) { put_back_token(pc); // c symbol } else { expect_token(pc, TokenIdRBracket); @@ -2924,8 +2836,8 @@ static AstNode *ast_parse_ptr_type_start(ParseContext *pc) { } } - Token *colon = eat_token_if(pc, TokenIdColon); - if (colon != nullptr) { + TokenIndex colon = eat_token_if(pc, TokenIdColon); + if (colon != 0) { sentinel = ast_expect(pc, ast_parse_expr); } expect_token(pc, TokenIdRBracket); @@ -2951,9 +2863,7 @@ static AstNode *ast_parse_container_decl_auto(ParseContext *pc) { res->data.container_decl.fields = members.fields; res->data.container_decl.decls = members.decls; - if (buf_len(&members.doc_comments) != 0) { - res->data.container_decl.doc_comments = members.doc_comments; - } + res->data.container_decl.doc_comments = members.doc_comments; return res; } @@ -2963,8 +2873,8 @@ static AstNode *ast_parse_container_decl_auto(ParseContext *pc) { // / KEYWORD_union (LPAREN (KEYWORD_enum (LPAREN Expr RPAREN)? / Expr) RPAREN)? // / KEYWORD_opaque static AstNode *ast_parse_container_decl_type(ParseContext *pc) { - Token *first = eat_token_if(pc, TokenIdKeywordStruct); - if (first != nullptr) { + TokenIndex first = eat_token_if(pc, TokenIdKeywordStruct); + if (first != 0) { AstNode *res = ast_create_node(pc, NodeTypeContainerDecl, first); res->data.container_decl.init_arg_expr = nullptr; res->data.container_decl.kind = ContainerKindStruct; @@ -2972,7 +2882,7 @@ static AstNode *ast_parse_container_decl_type(ParseContext *pc) { } first = eat_token_if(pc, TokenIdKeywordOpaque); - if (first != nullptr) { + if (first != 0) { AstNode *res = ast_create_node(pc, NodeTypeContainerDecl, first); res->data.container_decl.init_arg_expr = nullptr; res->data.container_decl.kind = ContainerKindOpaque; @@ -2980,9 +2890,9 @@ static AstNode *ast_parse_container_decl_type(ParseContext *pc) { } first = eat_token_if(pc, TokenIdKeywordEnum); - if (first != nullptr) { + if (first != 0) { AstNode *init_arg_expr = nullptr; - if (eat_token_if(pc, TokenIdLParen) != nullptr) { + if (eat_token_if(pc, TokenIdLParen) != 0) { init_arg_expr = ast_expect(pc, ast_parse_expr); expect_token(pc, TokenIdRParen); } @@ -2993,13 +2903,13 @@ static AstNode *ast_parse_container_decl_type(ParseContext *pc) { } first = eat_token_if(pc, TokenIdKeywordUnion); - if (first != nullptr) { + if (first != 0) { AstNode *init_arg_expr = nullptr; bool auto_enum = false; - if (eat_token_if(pc, TokenIdLParen) != nullptr) { - if (eat_token_if(pc, TokenIdKeywordEnum) != nullptr) { + if (eat_token_if(pc, TokenIdLParen) != 0) { + if (eat_token_if(pc, TokenIdKeywordEnum) != 0) { auto_enum = true; - if (eat_token_if(pc, TokenIdLParen) != nullptr) { + if (eat_token_if(pc, TokenIdLParen) != 0) { init_arg_expr = ast_expect(pc, ast_parse_expr); expect_token(pc, TokenIdRParen); } @@ -3022,7 +2932,7 @@ static AstNode *ast_parse_container_decl_type(ParseContext *pc) { // ByteAlign <- KEYWORD_align LPAREN Expr RPAREN static AstNode *ast_parse_byte_align(ParseContext *pc) { - if (eat_token_if(pc, TokenIdKeywordAlign) == nullptr) + if (eat_token_if(pc, TokenIdKeywordAlign) == 0) return nullptr; expect_token(pc, TokenIdLParen); @@ -3103,7 +3013,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont case NodeTypeCharLiteral: // none break; - case NodeTypeSymbol: + case NodeTypeIdentifier: // none break; case NodeTypePrefixOpExpr: @@ -3264,3 +3174,414 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont break; } } + +Error source_string_literal_buf(const char *source, Buf *out, size_t *bad_index) { + size_t byte_offset = 0; + + assert(source[byte_offset] == '"'); + byte_offset += 1; + + buf_resize(out, 0); + + uint32_t codepoint; + + enum { + StateStart, + StateBackslash, + StateUnicodeLBrace, + StateUnicodeDigit, + } state = StateStart; + for (;;byte_offset += 1) { + switch (state) { + case StateStart: switch (source[byte_offset]) { + case '\\': + state = StateBackslash; + continue; + case '\n': + *bad_index = byte_offset; + return ErrorInvalidCharacter; + case '"': + return ErrorNone; + default: + buf_append_char(out, source[byte_offset]); + continue; + } + case StateBackslash: switch (source[byte_offset]) { + case 'n': + buf_append_char(out, '\n'); + state = StateStart; + continue; + case 'r': + buf_append_char(out, '\r'); + state = StateStart; + continue; + case '\\': + buf_append_char(out, '\\'); + state = StateStart; + continue; + case 't': + buf_append_char(out, '\t'); + state = StateStart; + continue; + case '\'': + buf_append_char(out, '\''); + state = StateStart; + continue; + case '"': + buf_append_char(out, '"'); + state = StateStart; + continue; + case 'x': { + byte_offset += 1; + uint8_t digit1; + if (source[byte_offset] >= '0' && source[byte_offset] <= '9') { + digit1 = source[byte_offset] - '0'; + } else if (source[byte_offset] >= 'a' && source[byte_offset] <= 'z') { + digit1 = source[byte_offset] - 'a' + 10; + } else if (source[byte_offset] >= 'A' && source[byte_offset] <= 'Z') { + digit1 = source[byte_offset] - 'A' + 10; + } else { + *bad_index = byte_offset; + return ErrorInvalidCharacter; + } + + byte_offset += 1; + uint8_t digit0; + if (source[byte_offset] >= '0' && source[byte_offset] <= '9') { + digit0 = source[byte_offset] - '0'; + } else if (source[byte_offset] >= 'a' && source[byte_offset] <= 'z') { + digit0 = source[byte_offset] - 'a' + 10; + } else if (source[byte_offset] >= 'A' && source[byte_offset] <= 'Z') { + digit0 = source[byte_offset] - 'A' + 10; + } else { + *bad_index = byte_offset; + return ErrorInvalidCharacter; + } + + buf_append_char(out, digit1 * 16 + digit0); + state = StateStart; + continue; + } + case 'u': + state = StateUnicodeLBrace; + continue; + default: + *bad_index = byte_offset; + return ErrorInvalidCharacter; + } + case StateUnicodeLBrace: switch (source[byte_offset]) { + case '{': + state = StateUnicodeDigit; + codepoint = 0; + continue; + default: + *bad_index = byte_offset; + return ErrorInvalidCharacter; + } + case StateUnicodeDigit: { + uint8_t digit; + if (source[byte_offset] >= '0' && source[byte_offset] <= '9') { + digit = source[byte_offset] - '0'; + } else if (source[byte_offset] >= 'a' && source[byte_offset] <= 'z') { + digit = source[byte_offset] - 'a' + 10; + } else if (source[byte_offset] >= 'A' && source[byte_offset] <= 'Z') { + digit = source[byte_offset] - 'A' + 10; + } else if (source[byte_offset] == '}') { + if (codepoint < 0x80) { + buf_append_char(out, codepoint); + } else if (codepoint < 0x800) { + buf_append_char(out, 0xc0 | (codepoint >> 6)); + buf_append_char(out, 0x80 | (codepoint & 0x3f)); + } else if (codepoint < 0x10000) { + buf_append_char(out, 0xe0 | (codepoint >> 12)); + buf_append_char(out, 0x80 | ((codepoint >> 6) & 0x3f)); + buf_append_char(out, 0x80 | (codepoint & 0x3f)); + } else if (codepoint < 0x110000) { + buf_append_char(out, 0xf0 | (codepoint >> 18)); + buf_append_char(out, 0x80 | ((codepoint >> 12) & 0x3f)); + buf_append_char(out, 0x80 | ((codepoint >> 6) & 0x3f)); + buf_append_char(out, 0x80 | (codepoint & 0x3f)); + } else { + *bad_index = byte_offset; + return ErrorUnicodePointTooLarge; + } + state = StateStart; + continue; + } else { + *bad_index = byte_offset; + return ErrorInvalidCharacter; + } + codepoint = codepoint * 16 + digit; + continue; + } + } + } + zig_unreachable(); +} + +static uint32_t utf8_code_point(const uint8_t *bytes) { + if (bytes[0] <= 0x7f) { + return bytes[0]; + } else if (bytes[0] >= 0xc0 && bytes[0] <= 0xdf) { + uint32_t result = bytes[0] & 0x1f; + result <<= 6; + result |= bytes[1] & 0x3f; + return result; + } else if (bytes[0] >= 0xe0 && bytes[0] <= 0xef) { + uint32_t result = bytes[0] & 0xf; + + result <<= 6; + result |= bytes[1] & 0x3f; + + result <<= 6; + result |= bytes[2] & 0x3f; + + return result; + } else if (bytes[0] >= 0xf0 && bytes[0] <= 0xf7) { + uint32_t result = bytes[0] & 0x7; + + result <<= 6; + result |= bytes[1] & 0x3f; + + result <<= 6; + result |= bytes[2] & 0x3f; + + result <<= 6; + result |= bytes[3] & 0x3f; + + return result; + } else { + zig_unreachable(); + } +} + +Error source_char_literal(const char *source, uint32_t *result, size_t *bad_index) { + if (source[0] != '\\') { + *result = utf8_code_point((const uint8_t *)source); + return ErrorNone; + } + + uint32_t byte_offset = 1; + uint32_t codepoint; + + enum State { + StateBackslash, + StateUnicodeLBrace, + StateUnicodeDigit, + } state = StateBackslash; + + for (;;byte_offset += 1) { + switch (state) { + case StateBackslash: switch (source[byte_offset]) { + case 'n': + *result = '\n'; + return ErrorNone; + case 'r': + *result = '\r'; + return ErrorNone; + case '\\': + *result = '\\'; + return ErrorNone; + case 't': + *result = '\t'; + return ErrorNone; + case '\'': + *result = '\''; + return ErrorNone; + case '"': + *result = '"'; + return ErrorNone; + case 'x': { + byte_offset += 1; + uint8_t digit1; + if (source[byte_offset] >= '0' && source[byte_offset] <= '9') { + digit1 = source[byte_offset] - '0'; + } else if (source[byte_offset] >= 'a' && source[byte_offset] <= 'z') { + digit1 = source[byte_offset] - 'a' + 10; + } else if (source[byte_offset] >= 'A' && source[byte_offset] <= 'Z') { + digit1 = source[byte_offset] - 'A' + 10; + } else { + *bad_index = byte_offset; + return ErrorInvalidCharacter; + } + + byte_offset += 1; + uint8_t digit0; + if (source[byte_offset] >= '0' && source[byte_offset] <= '9') { + digit0 = source[byte_offset] - '0'; + } else if (source[byte_offset] >= 'a' && source[byte_offset] <= 'z') { + digit0 = source[byte_offset] - 'a' + 10; + } else if (source[byte_offset] >= 'A' && source[byte_offset] <= 'Z') { + digit0 = source[byte_offset] - 'A' + 10; + } else { + *bad_index = byte_offset; + return ErrorInvalidCharacter; + } + + *result = digit1 * 16 + digit0; + return ErrorNone; + } + case 'u': + state = StateUnicodeLBrace; + continue; + default: + *bad_index = byte_offset; + return ErrorInvalidCharacter; + } + case StateUnicodeLBrace: switch (source[byte_offset]) { + case '{': + state = StateUnicodeDigit; + codepoint = 0; + continue; + default: + *bad_index = byte_offset; + return ErrorInvalidCharacter; + } + case StateUnicodeDigit: { + uint8_t digit; + if (source[byte_offset] >= '0' && source[byte_offset] <= '9') { + digit = source[byte_offset] - '0'; + } else if (source[byte_offset] >= 'a' && source[byte_offset] <= 'z') { + digit = source[byte_offset] - 'a' + 10; + } else if (source[byte_offset] >= 'A' && source[byte_offset] <= 'Z') { + digit = source[byte_offset] - 'A' + 10; + } else if (source[byte_offset] == '}') { + if (codepoint < 0x110000) { + *result = codepoint; + return ErrorNone; + } else { + *bad_index = byte_offset; + return ErrorUnicodePointTooLarge; + } + } else { + *bad_index = byte_offset; + return ErrorInvalidCharacter; + } + codepoint = codepoint * 16 + digit; + continue; + } + } + } +} + + +Buf *token_string_literal_buf(RootStruct *root_struct, TokenIndex token) { + Error err; + assert(root_struct->token_ids[token] == TokenIdStringLiteral); + const char *source = buf_ptr(root_struct->source_code); + size_t byte_offset = root_struct->token_locs[token].offset; + size_t bad_index; + Buf *str = buf_alloc(); + if ((err = source_string_literal_buf(source + byte_offset, str, &bad_index))) { + zig_panic("TODO handle string literal parse error"); + } + return str; +} + +Buf *token_identifier_buf(RootStruct *root_struct, TokenIndex token) { + Error err; + const char *source = buf_ptr(root_struct->source_code); + size_t byte_offset = root_struct->token_locs[token].offset; + if (root_struct->token_ids[token] == TokenIdBuiltin) { + byte_offset += 1; + } else { + assert(root_struct->token_ids[token] == TokenIdIdentifier); + } + assert(source[byte_offset] != '.'); // wrong token index + + if (source[byte_offset] == '@') { + size_t bad_index; + Buf *str = buf_alloc(); + if ((err = source_string_literal_buf(source + byte_offset + 1, str, &bad_index))) { + zig_panic("TODO handle string literal parse error"); + } + return str; + } else { + size_t start = byte_offset; + for (;; byte_offset += 1) { + if (source[byte_offset] == 0) break; + if ((source[byte_offset] >= 'a' && source[byte_offset] <= 'z') || + (source[byte_offset] >= 'A' && source[byte_offset] <= 'Z') || + (source[byte_offset] >= '0' && source[byte_offset] <= '9') || + source[byte_offset] == '_') + { + continue; + } + break; + } + return buf_create_from_mem(source + start, byte_offset - start); + } +} + +Buf *node_identifier_buf(AstNode *node) { + assert(node->type == NodeTypeIdentifier); + RootStruct *root_struct = node->owner->data.structure.root_struct; + return token_identifier_buf(root_struct, node->main_token); +} + +Buf *node_string_literal_buf(AstNode *node) { + assert(node->type == NodeTypeStringLiteral); + RootStruct *root_struct = node->owner->data.structure.root_struct; + return token_string_literal_buf(root_struct, node->main_token); +} + +void token_number_literal_bigint(RootStruct *root_struct, BigInt *result, TokenIndex token) { + const char *source = buf_ptr(root_struct->source_code); + uint32_t byte_offset = root_struct->token_locs[token].offset; + + bigint_init_unsigned(result, 0); + BigInt radix_bi; + + if (source[byte_offset] == '0') { + byte_offset += 1; + switch (source[byte_offset]) { + case 'b': + byte_offset += 1; + bigint_init_unsigned(&radix_bi, 2); + break; + case 'o': + byte_offset += 1; + bigint_init_unsigned(&radix_bi, 8); + break; + case 'x': + byte_offset += 1; + bigint_init_unsigned(&radix_bi, 16); + break; + default: + bigint_init_unsigned(&radix_bi, 10); + break; + } + } else { + bigint_init_unsigned(&radix_bi, 10); + } + + BigInt digit_value_bi = {}; + BigInt multiplied = {}; + + for (;source[byte_offset] != 0; byte_offset += 1) { + uint8_t digit; + if (source[byte_offset] >= '0' && source[byte_offset] <= '9') { + digit = source[byte_offset] - '0'; + } else if (source[byte_offset] >= 'a' && source[byte_offset] <= 'z') { + digit = source[byte_offset] - 'a' + 10; + } else if (source[byte_offset] >= 'A' && source[byte_offset] <= 'Z') { + digit = source[byte_offset] - 'A' + 10; + } else if (source[byte_offset] == '_') { + continue; + } else { + break; + } + bigint_deinit(&digit_value_bi); + bigint_init_unsigned(&digit_value_bi, digit); + + bigint_deinit(&multiplied); + bigint_mul(&multiplied, result, &radix_bi); + + bigint_add(result, &multiplied, &digit_value_bi); + } + + bigint_deinit(&digit_value_bi); + bigint_deinit(&multiplied); + bigint_deinit(&radix_bi); +} + diff --git a/src/stage1/parser.hpp b/src/stage1/parser.hpp index 73950993f3..2d9a5f0b4a 100644 --- a/src/stage1/parser.hpp +++ b/src/stage1/parser.hpp @@ -12,14 +12,21 @@ #include "tokenizer.hpp" #include "errmsg.hpp" -ATTRIBUTE_PRINTF(2, 3) -void ast_token_error(Token *token, const char *format, ...); - - -AstNode * ast_parse(Buf *buf, ZigList *tokens, ZigType *owner, ErrColor err_color); +AstNode * ast_parse(Buf *buf, ZigType *owner, ErrColor err_color); void ast_print(AstNode *node, int indent); void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *context), void *context); +Buf *node_identifier_buf(AstNode *node); +Buf *node_string_literal_buf(AstNode *node); + +Buf *token_identifier_buf(RootStruct *root_struct, TokenIndex token); +Buf *token_string_literal_buf(RootStruct *root_struct, TokenIndex token); + +void token_number_literal_bigint(RootStruct *root_struct, BigInt *result, TokenIndex token); + +Error source_string_literal_buf(const char *source, Buf *out, size_t *bad_index); +Error source_char_literal(const char *source, uint32_t *out, size_t *bad_index); + #endif diff --git a/src/stage1/stage2.h b/src/stage1/stage2.h index 1eb494f362..b7c8616ec0 100644 --- a/src/stage1/stage2.h +++ b/src/stage1/stage2.h @@ -112,6 +112,8 @@ enum Error { ErrorZigIsTheCCompiler, ErrorFileBusy, ErrorLocked, + ErrorInvalidCharacter, + ErrorUnicodePointTooLarge, }; // ABI warning diff --git a/src/stage1/tokenizer.cpp b/src/stage1/tokenizer.cpp index 623169a313..b1bae1865b 100644 --- a/src/stage1/tokenizer.cpp +++ b/src/stage1/tokenizer.cpp @@ -30,18 +30,28 @@ case '7': \ case '8': \ case '9' + #define DIGIT \ '0': \ case DIGIT_NON_ZERO -#define ALPHA \ +#define HEXDIGIT \ 'a': \ case 'b': \ case 'c': \ case 'd': \ case 'e': \ case 'f': \ - case 'g': \ + case 'A': \ + case 'B': \ + case 'C': \ + case 'D': \ + case 'E': \ + case 'F': \ + case DIGIT + +#define ALPHA_EXCEPT_HEX_P_O_X \ + 'g': \ case 'h': \ case 'i': \ case 'j': \ @@ -49,8 +59,6 @@ case 'l': \ case 'm': \ case 'n': \ - case 'o': \ - case 'p': \ case 'q': \ case 'r': \ case 's': \ @@ -58,15 +66,8 @@ case 'u': \ case 'v': \ case 'w': \ - case 'x': \ case 'y': \ case 'z': \ - case 'A': \ - case 'B': \ - case 'C': \ - case 'D': \ - case 'E': \ - case 'F': \ case 'G': \ case 'H': \ case 'I': \ @@ -76,7 +77,6 @@ case 'M': \ case 'N': \ case 'O': \ - case 'P': \ case 'Q': \ case 'R': \ case 'S': \ @@ -88,7 +88,46 @@ case 'Y': \ case 'Z' -#define SYMBOL_CHAR \ +#define ALPHA_EXCEPT_E_B_O_X \ + ALPHA_EXCEPT_HEX_P_O_X: \ + case 'a': \ + case 'c': \ + case 'd': \ + case 'f': \ + case 'A': \ + case 'B': \ + case 'C': \ + case 'D': \ + case 'F': \ + case 'p': \ + case 'P' + +#define ALPHA_EXCEPT_HEX_AND_P \ + ALPHA_EXCEPT_HEX_P_O_X: \ + case 'o': \ + case 'x' + +#define ALPHA_EXCEPT_E \ + ALPHA_EXCEPT_HEX_AND_P: \ + case 'a': \ + case 'b': \ + case 'c': \ + case 'd': \ + case 'f': \ + case 'A': \ + case 'B': \ + case 'C': \ + case 'D': \ + case 'F': \ + case 'p': \ + case 'P' + +#define ALPHA \ + ALPHA_EXCEPT_E: \ + case 'e': \ + case 'E' + +#define IDENTIFIER_CHAR \ ALPHA: \ case DIGIT: \ case '_' @@ -157,101 +196,92 @@ static const struct ZigKeyword zig_keywords[] = { {"while", TokenIdKeywordWhile}, }; -bool is_zig_keyword(Buf *buf) { +// Returns TokenIdIdentifier if it is not a keyword. +static TokenId zig_keyword_token(const char *name_ptr, size_t name_len) { for (size_t i = 0; i < array_length(zig_keywords); i += 1) { - if (buf_eql_str(buf, zig_keywords[i].text)) { - return true; + if (mem_eql_str(name_ptr, name_len, zig_keywords[i].text)) { + return zig_keywords[i].token_id; } } - return false; -} - -static bool is_symbol_char(uint8_t c) { - switch (c) { - case SYMBOL_CHAR: - return true; - default: - return false; - } + return TokenIdIdentifier; } enum TokenizeState { - TokenizeStateStart, - TokenizeStateSymbol, - TokenizeStateZero, // "0", which might lead to "0x" - TokenizeStateNumber, // "123", "0x123" - TokenizeStateNumberNoUnderscore, // "12_", "0x12_" next char must be digit - TokenizeStateNumberDot, - TokenizeStateFloatFraction, // "123.456", "0x123.456" - TokenizeStateFloatFractionNoUnderscore, // "123.45_", "0x123.45_" - TokenizeStateFloatExponentUnsigned, // "123.456e", "123e", "0x123p" - TokenizeStateFloatExponentNumber, // "123.456e7", "123.456e+7", "123.456e-7" - TokenizeStateFloatExponentNumberNoUnderscore, // "123.456e7_", "123.456e+7_", "123.456e-7_" - TokenizeStateString, - TokenizeStateStringEscape, - TokenizeStateStringEscapeUnicodeStart, - TokenizeStateCharLiteral, - TokenizeStateCharLiteralEnd, - TokenizeStateCharLiteralUnicode, - TokenizeStateSawStar, - TokenizeStateSawStarPercent, - TokenizeStateSawSlash, - TokenizeStateSawSlash2, - TokenizeStateSawSlash3, - TokenizeStateSawSlashBang, - TokenizeStateSawBackslash, - TokenizeStateSawPercent, - TokenizeStateSawPlus, - TokenizeStateSawPlusPercent, - TokenizeStateSawDash, - TokenizeStateSawMinusPercent, - TokenizeStateSawAmpersand, - TokenizeStateSawCaret, - TokenizeStateSawBar, - TokenizeStateDocComment, - TokenizeStateContainerDocComment, - TokenizeStateLineComment, - TokenizeStateLineString, - TokenizeStateLineStringEnd, - TokenizeStateLineStringContinue, - TokenizeStateSawEq, - TokenizeStateSawBang, - TokenizeStateSawLessThan, - TokenizeStateSawLessThanLessThan, - TokenizeStateSawGreaterThan, - TokenizeStateSawGreaterThanGreaterThan, - TokenizeStateSawDot, - TokenizeStateSawDotDot, - TokenizeStateSawDotStar, - TokenizeStateSawAtSign, - TokenizeStateCharCode, - TokenizeStateError, + TokenizeState_start, + TokenizeState_identifier, + TokenizeState_builtin, + TokenizeState_string_literal, + TokenizeState_string_literal_backslash, + TokenizeState_multiline_string_literal_line, + TokenizeState_char_literal, + TokenizeState_char_literal_backslash, + TokenizeState_char_literal_hex_escape, + TokenizeState_char_literal_unicode_escape_saw_u, + TokenizeState_char_literal_unicode_escape, + TokenizeState_char_literal_unicode, + TokenizeState_char_literal_end, + TokenizeState_backslash, + TokenizeState_equal, + TokenizeState_bang, + TokenizeState_pipe, + TokenizeState_minus, + TokenizeState_minus_percent, + TokenizeState_asterisk, + TokenizeState_asterisk_percent, + TokenizeState_slash, + TokenizeState_line_comment_start, + TokenizeState_line_comment, + TokenizeState_doc_comment_start, + TokenizeState_doc_comment, + TokenizeState_container_doc_comment, + TokenizeState_zero, + TokenizeState_int_literal_dec, + TokenizeState_int_literal_dec_no_underscore, + TokenizeState_int_literal_bin, + TokenizeState_int_literal_bin_no_underscore, + TokenizeState_int_literal_oct, + TokenizeState_int_literal_oct_no_underscore, + TokenizeState_int_literal_hex, + TokenizeState_int_literal_hex_no_underscore, + TokenizeState_num_dot_dec, + TokenizeState_num_dot_hex, + TokenizeState_float_fraction_dec, + TokenizeState_float_fraction_dec_no_underscore, + TokenizeState_float_fraction_hex, + TokenizeState_float_fraction_hex_no_underscore, + TokenizeState_float_exponent_unsigned, + TokenizeState_float_exponent_num, + TokenizeState_float_exponent_num_no_underscore, + TokenizeState_ampersand, + TokenizeState_caret, + TokenizeState_percent, + TokenizeState_plus, + TokenizeState_plus_percent, + TokenizeState_angle_bracket_left, + TokenizeState_angle_bracket_angle_bracket_left, + TokenizeState_angle_bracket_right, + TokenizeState_angle_bracket_angle_bracket_right, + TokenizeState_period, + TokenizeState_period_2, + TokenizeState_period_asterisk, + TokenizeState_saw_at_sign, + TokenizeState_error, }; struct Tokenize { - Buf *buf; + Tokenization *out; size_t pos; TokenizeState state; - ZigList *tokens; - int line; - int column; - Token *cur_tok; - Tokenization *out; - uint32_t radix; - bool is_trailing_underscore; - size_t char_code_index; - bool unicode; - uint32_t char_code; - size_t remaining_code_units; + uint32_t line; + uint32_t column; }; ATTRIBUTE_PRINTF(2, 3) static void tokenize_error(Tokenize *t, const char *format, ...) { - t->state = TokenizeStateError; + t->state = TokenizeState_error; - t->out->err_line = t->line; - t->out->err_column = t->column; + t->out->err_byte_offset = t->pos; va_list ap; va_start(ap, format); @@ -259,98 +289,18 @@ static void tokenize_error(Tokenize *t, const char *format, ...) { va_end(ap); } -static void set_token_id(Tokenize *t, Token *token, TokenId id) { - token->id = id; - - if (id == TokenIdIntLiteral) { - bigint_init_unsigned(&token->data.int_lit.bigint, 0); - } else if (id == TokenIdFloatLiteral) { - bigfloat_init_32(&token->data.float_lit.bigfloat, 0.0f); - token->data.float_lit.overflow = false; - } else if (id == TokenIdStringLiteral || id == TokenIdMultilineStringLiteral || id == TokenIdSymbol) { - memset(&token->data.str_lit.str, 0, sizeof(Buf)); - buf_resize(&token->data.str_lit.str, 0); - } -} - static void begin_token(Tokenize *t, TokenId id) { - assert(!t->cur_tok); - t->tokens->add_one(); - Token *token = &t->tokens->last(); - token->start_line = t->line; - token->start_column = t->column; - token->start_pos = t->pos; - - set_token_id(t, token, id); - - t->cur_tok = token; + t->out->ids.append(id); + t->out->locs.append({ + .offset = (uint32_t) t->pos, + .line = t->line, + .column = t->column, + }); } static void cancel_token(Tokenize *t) { - t->tokens->pop(); - t->cur_tok = nullptr; -} - -static void end_float_token(Tokenize *t) { - uint8_t *ptr_buf = (uint8_t*)buf_ptr(t->buf) + t->cur_tok->start_pos; - size_t buf_len = t->cur_tok->end_pos - t->cur_tok->start_pos; - if (bigfloat_init_buf(&t->cur_tok->data.float_lit.bigfloat, ptr_buf, buf_len)) { - t->cur_tok->data.float_lit.overflow = true; - } -} - -static void end_token(Tokenize *t) { - assert(t->cur_tok); - t->cur_tok->end_pos = t->pos + 1; - - if (t->cur_tok->id == TokenIdFloatLiteral) { - end_float_token(t); - } else if (t->cur_tok->id == TokenIdSymbol) { - char *token_mem = buf_ptr(t->buf) + t->cur_tok->start_pos; - int token_len = (int)(t->cur_tok->end_pos - t->cur_tok->start_pos); - - for (size_t i = 0; i < array_length(zig_keywords); i += 1) { - if (mem_eql_str(token_mem, token_len, zig_keywords[i].text)) { - t->cur_tok->id = zig_keywords[i].token_id; - break; - } - } - } - - t->cur_tok = nullptr; -} - -static bool is_exponent_signifier(uint8_t c, int radix) { - if (radix == 16) { - return c == 'p' || c == 'P'; - } else { - return c == 'e' || c == 'E'; - } -} - -static uint32_t get_digit_value(uint8_t c) { - if ('0' <= c && c <= '9') { - return c - '0'; - } - if ('A' <= c && c <= 'Z') { - return c - 'A' + 10; - } - if ('a' <= c && c <= 'z') { - return c - 'a' + 10; - } - return UINT32_MAX; -} - -static void handle_string_escape(Tokenize *t, uint8_t c) { - if (t->cur_tok->id == TokenIdCharLiteral) { - t->cur_tok->data.char_lit.c = c; - t->state = TokenizeStateCharLiteralEnd; - } else if (t->cur_tok->id == TokenIdStringLiteral || t->cur_tok->id == TokenIdSymbol) { - buf_append_char(&t->cur_tok->data.str_lit.str, c); - t->state = TokenizeStateString; - } else { - zig_unreachable(); - } + t->out->ids.pop(); + t->out->locs.pop(); } static const char* get_escape_shorthand(uint8_t c) { @@ -376,7 +326,15 @@ static const char* get_escape_shorthand(uint8_t c) { } } +static void invalid_eof(Tokenize *t) { + return tokenize_error(t, "unexpected End-Of-File"); +} + static void invalid_char_error(Tokenize *t, uint8_t c) { + if (c == 0) { + return invalid_eof(t); + } + if (c == '\r') { tokenize_error(t, "invalid carriage return, only '\\n' line endings are supported"); return; @@ -396,1139 +354,1092 @@ static void invalid_char_error(Tokenize *t, uint8_t c) { tokenize_error(t, "invalid character: '\\x%02x'", c); } -void tokenize(Buf *buf, Tokenization *out) { +void tokenize(const char *source, Tokenization *out) { Tokenize t = {0}; t.out = out; - t.tokens = out->tokens = heap::c_allocator.create>(); - t.buf = buf; - out->line_offsets = heap::c_allocator.create>(); - out->line_offsets->append(0); + size_t remaining_code_units; + size_t seen_escape_digits; - // Skip the UTF-8 BOM if present - if (buf_starts_with_mem(buf, "\xEF\xBB\xBF", 3)) { + // Skip the UTF-8 BOM if present. + if (source[0] == (char)0xef && + source[1] == (char)0xbb && + source[2] == (char)0xbf) + { t.pos += 3; } - for (; t.pos < buf_len(t.buf); t.pos += 1) { - uint8_t c = buf_ptr(t.buf)[t.pos]; + // Invalid token takes up index 0 so that index 0 can mean "none". + begin_token(&t, TokenIdCount); + + for (;;) { + uint8_t c = source[t.pos]; switch (t.state) { - case TokenizeStateError: - break; - case TokenizeStateStart: + case TokenizeState_error: + goto eof; + case TokenizeState_start: switch (c) { + case 0: + goto eof; case WHITESPACE: break; - case ALPHA: - case '_': - t.state = TokenizeStateSymbol; - begin_token(&t, TokenIdSymbol); - buf_append_char(&t.cur_tok->data.str_lit.str, c); - break; - case '0': - t.state = TokenizeStateZero; - begin_token(&t, TokenIdIntLiteral); - t.is_trailing_underscore = false; - t.radix = 10; - bigint_init_unsigned(&t.cur_tok->data.int_lit.bigint, 0); - break; - case DIGIT_NON_ZERO: - t.state = TokenizeStateNumber; - begin_token(&t, TokenIdIntLiteral); - t.is_trailing_underscore = false; - t.radix = 10; - bigint_init_unsigned(&t.cur_tok->data.int_lit.bigint, get_digit_value(c)); - break; case '"': begin_token(&t, TokenIdStringLiteral); - t.state = TokenizeStateString; + t.state = TokenizeState_string_literal; break; case '\'': begin_token(&t, TokenIdCharLiteral); - t.state = TokenizeStateCharLiteral; + t.state = TokenizeState_char_literal; break; - case '(': - begin_token(&t, TokenIdLParen); - end_token(&t); - break; - case ')': - begin_token(&t, TokenIdRParen); - end_token(&t); - break; - case ',': - begin_token(&t, TokenIdComma); - end_token(&t); - break; - case '?': - begin_token(&t, TokenIdQuestion); - end_token(&t); - break; - case '{': - begin_token(&t, TokenIdLBrace); - end_token(&t); - break; - case '}': - begin_token(&t, TokenIdRBrace); - end_token(&t); - break; - case '[': - begin_token(&t, TokenIdLBracket); - end_token(&t); - break; - case ']': - begin_token(&t, TokenIdRBracket); - end_token(&t); - break; - case ';': - begin_token(&t, TokenIdSemicolon); - end_token(&t); - break; - case ':': - begin_token(&t, TokenIdColon); - end_token(&t); - break; - case '#': - begin_token(&t, TokenIdNumberSign); - end_token(&t); - break; - case '*': - begin_token(&t, TokenIdStar); - t.state = TokenizeStateSawStar; - break; - case '/': - begin_token(&t, TokenIdSlash); - t.state = TokenizeStateSawSlash; - break; - case '\\': - begin_token(&t, TokenIdMultilineStringLiteral); - t.state = TokenizeStateSawBackslash; - break; - case '%': - begin_token(&t, TokenIdPercent); - t.state = TokenizeStateSawPercent; - break; - case '+': - begin_token(&t, TokenIdPlus); - t.state = TokenizeStateSawPlus; - break; - case '~': - begin_token(&t, TokenIdTilde); - end_token(&t); + case ALPHA: + case '_': + t.state = TokenizeState_identifier; + begin_token(&t, TokenIdIdentifier); break; case '@': - begin_token(&t, TokenIdAtSign); - t.state = TokenizeStateSawAtSign; - break; - case '-': - begin_token(&t, TokenIdDash); - t.state = TokenizeStateSawDash; - break; - case '&': - begin_token(&t, TokenIdAmpersand); - t.state = TokenizeStateSawAmpersand; - break; - case '^': - begin_token(&t, TokenIdBinXor); - t.state = TokenizeStateSawCaret; - break; - case '|': - begin_token(&t, TokenIdBinOr); - t.state = TokenizeStateSawBar; + begin_token(&t, TokenIdBuiltin); + t.state = TokenizeState_saw_at_sign; break; case '=': begin_token(&t, TokenIdEq); - t.state = TokenizeStateSawEq; + t.state = TokenizeState_equal; break; case '!': begin_token(&t, TokenIdBang); - t.state = TokenizeStateSawBang; + t.state = TokenizeState_bang; + break; + case '|': + begin_token(&t, TokenIdBinOr); + t.state = TokenizeState_pipe; + break; + case '(': + begin_token(&t, TokenIdLParen); + break; + case ')': + begin_token(&t, TokenIdRParen); + break; + case '[': + begin_token(&t, TokenIdLBracket); + break; + case ']': + begin_token(&t, TokenIdRBracket); + break; + case ';': + begin_token(&t, TokenIdSemicolon); + break; + case ',': + begin_token(&t, TokenIdComma); + break; + case '?': + begin_token(&t, TokenIdQuestion); + break; + case ':': + begin_token(&t, TokenIdColon); + break; + case '%': + begin_token(&t, TokenIdPercent); + t.state = TokenizeState_percent; + break; + case '*': + begin_token(&t, TokenIdStar); + t.state = TokenizeState_asterisk; + break; + case '+': + begin_token(&t, TokenIdPlus); + t.state = TokenizeState_plus; break; case '<': begin_token(&t, TokenIdCmpLessThan); - t.state = TokenizeStateSawLessThan; + t.state = TokenizeState_angle_bracket_left; break; case '>': begin_token(&t, TokenIdCmpGreaterThan); - t.state = TokenizeStateSawGreaterThan; + t.state = TokenizeState_angle_bracket_right; + break; + case '^': + begin_token(&t, TokenIdBinXor); + t.state = TokenizeState_caret; + break; + case '\\': + begin_token(&t, TokenIdMultilineStringLiteralLine); + t.state = TokenizeState_backslash; + break; + case '{': + begin_token(&t, TokenIdLBrace); + break; + case '}': + begin_token(&t, TokenIdRBrace); + break; + case '~': + begin_token(&t, TokenIdTilde); break; case '.': begin_token(&t, TokenIdDot); - t.state = TokenizeStateSawDot; + t.state = TokenizeState_period; + break; + case '-': + begin_token(&t, TokenIdDash); + t.state = TokenizeState_minus; + break; + case '/': + begin_token(&t, TokenIdSlash); + t.state = TokenizeState_slash; + break; + case '&': + begin_token(&t, TokenIdAmpersand); + t.state = TokenizeState_ampersand; + break; + case '0': + t.state = TokenizeState_zero; + begin_token(&t, TokenIdIntLiteral); + break; + case DIGIT_NON_ZERO: + t.state = TokenizeState_int_literal_dec; + begin_token(&t, TokenIdIntLiteral); break; default: invalid_char_error(&t, c); } break; - case TokenizeStateSawDot: + case TokenizeState_saw_at_sign: switch (c) { - case '.': - t.state = TokenizeStateSawDotDot; - set_token_id(&t, t.cur_tok, TokenIdEllipsis2); + case 0: + invalid_eof(&t); + goto eof; + case '"': + t.out->ids.last() = TokenIdIdentifier; + t.state = TokenizeState_string_literal; break; - case '*': - t.state = TokenizeStateSawDotStar; - set_token_id(&t, t.cur_tok, TokenIdDotStar); + case IDENTIFIER_CHAR: + t.state = TokenizeState_builtin; break; default: - t.pos -= 1; - end_token(&t); - t.state = TokenizeStateStart; - continue; + invalid_char_error(&t, c); } break; - case TokenizeStateSawDotDot: - switch (c) { - case '.': - t.state = TokenizeStateStart; - set_token_id(&t, t.cur_tok, TokenIdEllipsis3); - end_token(&t); - break; - default: - t.pos -= 1; - end_token(&t); - t.state = TokenizeStateStart; - continue; - } - break; - case TokenizeStateSawDotStar: - switch (c) { - case '*': - tokenize_error(&t, "`.*` can't be followed by `*`. Are you missing a space?"); - break; - default: - t.pos -= 1; - end_token(&t); - t.state = TokenizeStateStart; - continue; - } - break; - case TokenizeStateSawGreaterThan: - switch (c) { - case '=': - set_token_id(&t, t.cur_tok, TokenIdCmpGreaterOrEq); - end_token(&t); - t.state = TokenizeStateStart; - break; - case '>': - set_token_id(&t, t.cur_tok, TokenIdBitShiftRight); - t.state = TokenizeStateSawGreaterThanGreaterThan; - break; - default: - t.pos -= 1; - end_token(&t); - t.state = TokenizeStateStart; - continue; - } - break; - case TokenizeStateSawGreaterThanGreaterThan: - switch (c) { - case '=': - set_token_id(&t, t.cur_tok, TokenIdBitShiftRightEq); - end_token(&t); - t.state = TokenizeStateStart; - break; - default: - t.pos -= 1; - end_token(&t); - t.state = TokenizeStateStart; - continue; - } - break; - case TokenizeStateSawLessThan: - switch (c) { - case '=': - set_token_id(&t, t.cur_tok, TokenIdCmpLessOrEq); - end_token(&t); - t.state = TokenizeStateStart; - break; - case '<': - set_token_id(&t, t.cur_tok, TokenIdBitShiftLeft); - t.state = TokenizeStateSawLessThanLessThan; - break; - default: - t.pos -= 1; - end_token(&t); - t.state = TokenizeStateStart; - continue; - } - break; - case TokenizeStateSawLessThanLessThan: - switch (c) { - case '=': - set_token_id(&t, t.cur_tok, TokenIdBitShiftLeftEq); - end_token(&t); - t.state = TokenizeStateStart; - break; - default: - t.pos -= 1; - end_token(&t); - t.state = TokenizeStateStart; - continue; - } - break; - case TokenizeStateSawBang: - switch (c) { - case '=': - set_token_id(&t, t.cur_tok, TokenIdCmpNotEq); - end_token(&t); - t.state = TokenizeStateStart; - break; - default: - t.pos -= 1; - end_token(&t); - t.state = TokenizeStateStart; - continue; - } - break; - case TokenizeStateSawEq: - switch (c) { - case '=': - set_token_id(&t, t.cur_tok, TokenIdCmpEq); - end_token(&t); - t.state = TokenizeStateStart; - break; - case '>': - set_token_id(&t, t.cur_tok, TokenIdFatArrow); - end_token(&t); - t.state = TokenizeStateStart; - break; - default: - t.pos -= 1; - end_token(&t); - t.state = TokenizeStateStart; - continue; - } - break; - case TokenizeStateSawStar: - switch (c) { - case '=': - set_token_id(&t, t.cur_tok, TokenIdTimesEq); - end_token(&t); - t.state = TokenizeStateStart; - break; - case '*': - set_token_id(&t, t.cur_tok, TokenIdStarStar); - end_token(&t); - t.state = TokenizeStateStart; - break; - case '%': - set_token_id(&t, t.cur_tok, TokenIdTimesPercent); - t.state = TokenizeStateSawStarPercent; - break; - default: - t.pos -= 1; - end_token(&t); - t.state = TokenizeStateStart; - continue; - } - break; - case TokenizeStateSawStarPercent: - switch (c) { - case '=': - set_token_id(&t, t.cur_tok, TokenIdTimesPercentEq); - end_token(&t); - t.state = TokenizeStateStart; - break; - default: - t.pos -= 1; - end_token(&t); - t.state = TokenizeStateStart; - continue; - } - break; - case TokenizeStateSawPercent: - switch (c) { - case '=': - set_token_id(&t, t.cur_tok, TokenIdModEq); - end_token(&t); - t.state = TokenizeStateStart; - break; - case '.': - set_token_id(&t, t.cur_tok, TokenIdPercentDot); - end_token(&t); - t.state = TokenizeStateStart; - break; - default: - t.pos -= 1; - end_token(&t); - t.state = TokenizeStateStart; - continue; - } - break; - case TokenizeStateSawPlus: - switch (c) { - case '=': - set_token_id(&t, t.cur_tok, TokenIdPlusEq); - end_token(&t); - t.state = TokenizeStateStart; - break; - case '+': - set_token_id(&t, t.cur_tok, TokenIdPlusPlus); - end_token(&t); - t.state = TokenizeStateStart; - break; - case '%': - set_token_id(&t, t.cur_tok, TokenIdPlusPercent); - t.state = TokenizeStateSawPlusPercent; - break; - default: - t.pos -= 1; - end_token(&t); - t.state = TokenizeStateStart; - continue; - } - break; - case TokenizeStateSawPlusPercent: - switch (c) { - case '=': - set_token_id(&t, t.cur_tok, TokenIdPlusPercentEq); - end_token(&t); - t.state = TokenizeStateStart; - break; - default: - t.pos -= 1; - end_token(&t); - t.state = TokenizeStateStart; - continue; - } - break; - case TokenizeStateSawAmpersand: + case TokenizeState_ampersand: switch (c) { + case 0: + goto eof; case '&': tokenize_error(&t, "`&&` is invalid. Note that `and` is boolean AND"); break; case '=': - set_token_id(&t, t.cur_tok, TokenIdBitAndEq); - end_token(&t); - t.state = TokenizeStateStart; + t.out->ids.last() = TokenIdBitAndEq; + t.state = TokenizeState_start; break; default: - t.pos -= 1; - end_token(&t); - t.state = TokenizeStateStart; + t.state = TokenizeState_start; continue; } break; - case TokenizeStateSawCaret: + case TokenizeState_asterisk: switch (c) { + case 0: + goto eof; case '=': - set_token_id(&t, t.cur_tok, TokenIdBitXorEq); - end_token(&t); - t.state = TokenizeStateStart; + t.out->ids.last() = TokenIdTimesEq; + t.state = TokenizeState_start; + break; + case '*': + t.out->ids.last() = TokenIdStarStar; + t.state = TokenizeState_start; + break; + case '%': + t.state = TokenizeState_asterisk_percent; break; default: - t.pos -= 1; - end_token(&t); - t.state = TokenizeStateStart; + t.state = TokenizeState_start; continue; } break; - case TokenizeStateSawBar: + case TokenizeState_asterisk_percent: switch (c) { + case 0: + t.out->ids.last() = TokenIdTimesPercent; + goto eof; case '=': - set_token_id(&t, t.cur_tok, TokenIdBitOrEq); - end_token(&t); - t.state = TokenizeStateStart; - break; - case '|': - set_token_id(&t, t.cur_tok, TokenIdBarBar); - end_token(&t); - t.state = TokenizeStateStart; + t.out->ids.last() = TokenIdTimesPercentEq; + t.state = TokenizeState_start; break; default: - t.pos -= 1; - end_token(&t); - t.state = TokenizeStateStart; + t.out->ids.last() = TokenIdTimesPercent; + t.state = TokenizeState_start; continue; } break; - case TokenizeStateSawSlash: + case TokenizeState_percent: switch (c) { - case '/': - t.state = TokenizeStateSawSlash2; - break; + case 0: + goto eof; case '=': - set_token_id(&t, t.cur_tok, TokenIdDivEq); - end_token(&t); - t.state = TokenizeStateStart; + t.out->ids.last() = TokenIdModEq; + t.state = TokenizeState_start; break; default: - t.pos -= 1; - end_token(&t); - t.state = TokenizeStateStart; + t.state = TokenizeState_start; continue; } break; - case TokenizeStateSawSlash2: + case TokenizeState_plus: switch (c) { - case '/': - t.state = TokenizeStateSawSlash3; + case 0: + goto eof; + case '=': + t.out->ids.last() = TokenIdPlusEq; + t.state = TokenizeState_start; break; - case '!': - t.state = TokenizeStateSawSlashBang; + case '+': + t.out->ids.last() = TokenIdPlusPlus; + t.state = TokenizeState_start; break; - case '\n': - cancel_token(&t); - t.state = TokenizeStateStart; + case '%': + t.state = TokenizeState_plus_percent; break; default: - cancel_token(&t); - t.state = TokenizeStateLineComment; - break; + t.state = TokenizeState_start; + continue; } break; - case TokenizeStateSawSlash3: + case TokenizeState_plus_percent: switch (c) { - case '/': - cancel_token(&t); - t.state = TokenizeStateLineComment; - break; - case '\n': - set_token_id(&t, t.cur_tok, TokenIdDocComment); - end_token(&t); - t.state = TokenizeStateStart; + case 0: + t.out->ids.last() = TokenIdPlusPercent; + goto eof; + case '=': + t.out->ids.last() = TokenIdPlusPercentEq; + t.state = TokenizeState_start; break; default: - set_token_id(&t, t.cur_tok, TokenIdDocComment); - t.state = TokenizeStateDocComment; - break; + t.out->ids.last() = TokenIdPlusPercent; + t.state = TokenizeState_start; + continue; } break; - case TokenizeStateSawSlashBang: + case TokenizeState_caret: switch (c) { - case '\n': - set_token_id(&t, t.cur_tok, TokenIdContainerDocComment); - end_token(&t); - t.state = TokenizeStateStart; + case 0: + goto eof; + case '=': + t.out->ids.last() = TokenIdBitXorEq; + t.state = TokenizeState_start; break; default: - set_token_id(&t, t.cur_tok, TokenIdContainerDocComment); - t.state = TokenizeStateContainerDocComment; - break; + t.state = TokenizeState_start; + continue; } break; - case TokenizeStateSawBackslash: + case TokenizeState_identifier: + switch (c) { + case 0: { + uint32_t start_pos = t.out->locs.last().offset; + t.out->ids.last() = zig_keyword_token( + source + start_pos, t.pos - start_pos); + goto eof; + } + case IDENTIFIER_CHAR: + break; + default: { + uint32_t start_pos = t.out->locs.last().offset; + t.out->ids.last() = zig_keyword_token( + source + start_pos, t.pos - start_pos); + + t.state = TokenizeState_start; + continue; + } + } + break; + case TokenizeState_builtin: + switch (c) { + case 0: + goto eof; + case IDENTIFIER_CHAR: + break; + default: + t.state = TokenizeState_start; + continue; + } + break; + case TokenizeState_backslash: switch (c) { case '\\': - t.state = TokenizeStateLineString; + t.state = TokenizeState_multiline_string_literal_line; break; default: invalid_char_error(&t, c); break; } break; - case TokenizeStateLineString: + case TokenizeState_string_literal: switch (c) { - case '\n': - t.state = TokenizeStateLineStringEnd; - break; - default: - buf_append_char(&t.cur_tok->data.str_lit.str, c); - break; - } - break; - case TokenizeStateLineStringEnd: - switch (c) { - case WHITESPACE: - break; + case 0: + invalid_eof(&t); + goto eof; case '\\': - t.state = TokenizeStateLineStringContinue; + t.state = TokenizeState_string_literal_backslash; break; - default: - t.pos -= 1; - end_token(&t); - t.state = TokenizeStateStart; - continue; - } - break; - case TokenizeStateLineStringContinue: - switch (c) { - case '\\': - t.state = TokenizeStateLineString; - buf_append_char(&t.cur_tok->data.str_lit.str, '\n'); - break; - default: - invalid_char_error(&t, c); - break; - } - break; - case TokenizeStateLineComment: - switch (c) { - case '\n': - t.state = TokenizeStateStart; - break; - default: - // do nothing - break; - } - break; - case TokenizeStateDocComment: - switch (c) { - case '\n': - end_token(&t); - t.state = TokenizeStateStart; - break; - default: - // do nothing - break; - } - break; - case TokenizeStateContainerDocComment: - switch (c) { - case '\n': - end_token(&t); - t.state = TokenizeStateStart; - break; - default: - // do nothing - break; - } - break; - case TokenizeStateSawAtSign: - switch (c) { case '"': - set_token_id(&t, t.cur_tok, TokenIdSymbol); - t.state = TokenizeStateString; - break; - default: - t.pos -= 1; - end_token(&t); - t.state = TokenizeStateStart; - continue; - } - break; - case TokenizeStateSymbol: - switch (c) { - case SYMBOL_CHAR: - buf_append_char(&t.cur_tok->data.str_lit.str, c); - break; - default: - t.pos -= 1; - end_token(&t); - t.state = TokenizeStateStart; - continue; - } - break; - case TokenizeStateString: - switch (c) { - case '"': - end_token(&t); - t.state = TokenizeStateStart; + t.state = TokenizeState_start; break; case '\n': + case '\r': tokenize_error(&t, "newline not allowed in string literal"); break; - case '\\': - t.state = TokenizeStateStringEscape; - break; default: - buf_append_char(&t.cur_tok->data.str_lit.str, c); break; } break; - case TokenizeStateStringEscape: + case TokenizeState_string_literal_backslash: switch (c) { - case 'x': - t.state = TokenizeStateCharCode; - t.radix = 16; - t.char_code = 0; - t.char_code_index = 0; - t.unicode = false; - break; - case 'u': - t.state = TokenizeStateStringEscapeUnicodeStart; - break; - case 'n': - handle_string_escape(&t, '\n'); - break; - case 'r': - handle_string_escape(&t, '\r'); - break; - case '\\': - handle_string_escape(&t, '\\'); - break; - case 't': - handle_string_escape(&t, '\t'); - break; - case '\'': - handle_string_escape(&t, '\''); - break; - case '"': - handle_string_escape(&t, '\"'); + case 0: + invalid_eof(&t); + goto eof; + case '\n': + case '\r': + tokenize_error(&t, "newline not allowed in string literal"); break; default: - invalid_char_error(&t, c); + t.state = TokenizeState_string_literal; + break; } break; - case TokenizeStateStringEscapeUnicodeStart: - switch (c) { - case '{': - t.state = TokenizeStateCharCode; - t.radix = 16; - t.char_code = 0; - t.char_code_index = 0; - t.unicode = true; - break; - default: - invalid_char_error(&t, c); - } - break; - case TokenizeStateCharCode: - { - if (t.unicode && c == '}') { - if (t.char_code_index == 0) { - tokenize_error(&t, "empty unicode escape sequence"); - break; - } - if (t.char_code > 0x10ffff) { - tokenize_error(&t, "unicode value out of range: %x", t.char_code); - break; - } - if (t.cur_tok->id == TokenIdCharLiteral) { - t.cur_tok->data.char_lit.c = t.char_code; - t.state = TokenizeStateCharLiteralEnd; - } else if (t.char_code <= 0x7f) { - // 00000000 00000000 00000000 0xxxxxxx - handle_string_escape(&t, (uint8_t)t.char_code); - } else if (t.char_code <= 0x7ff) { - // 00000000 00000000 00000xxx xx000000 - handle_string_escape(&t, (uint8_t)(0xc0 | (t.char_code >> 6))); - // 00000000 00000000 00000000 00xxxxxx - handle_string_escape(&t, (uint8_t)(0x80 | (t.char_code & 0x3f))); - } else if (t.char_code <= 0xffff) { - // 00000000 00000000 xxxx0000 00000000 - handle_string_escape(&t, (uint8_t)(0xe0 | (t.char_code >> 12))); - // 00000000 00000000 0000xxxx xx000000 - handle_string_escape(&t, (uint8_t)(0x80 | ((t.char_code >> 6) & 0x3f))); - // 00000000 00000000 00000000 00xxxxxx - handle_string_escape(&t, (uint8_t)(0x80 | (t.char_code & 0x3f))); - } else if (t.char_code <= 0x10ffff) { - // 00000000 000xxx00 00000000 00000000 - handle_string_escape(&t, (uint8_t)(0xf0 | (t.char_code >> 18))); - // 00000000 000000xx xxxx0000 00000000 - handle_string_escape(&t, (uint8_t)(0x80 | ((t.char_code >> 12) & 0x3f))); - // 00000000 00000000 0000xxxx xx000000 - handle_string_escape(&t, (uint8_t)(0x80 | ((t.char_code >> 6) & 0x3f))); - // 00000000 00000000 00000000 00xxxxxx - handle_string_escape(&t, (uint8_t)(0x80 | (t.char_code & 0x3f))); - } else { - zig_unreachable(); - } - break; - } - - uint32_t digit_value = get_digit_value(c); - if (digit_value >= t.radix) { - tokenize_error(&t, "invalid digit: '%c'", c); - break; - } - t.char_code *= t.radix; - t.char_code += digit_value; - t.char_code_index += 1; - - if (!t.unicode && t.char_code_index >= 2) { - assert(t.char_code <= 255); - handle_string_escape(&t, (uint8_t)t.char_code); - } - } - break; - case TokenizeStateCharLiteral: - if (c == '\'') { - tokenize_error(&t, "expected character"); + case TokenizeState_char_literal: + if (c == 0) { + invalid_eof(&t); + goto eof; } else if (c == '\\') { - t.state = TokenizeStateStringEscape; + t.state = TokenizeState_char_literal_backslash; + } else if (c == '\'') { + tokenize_error(&t, "expected character"); } else if ((c >= 0x80 && c <= 0xbf) || c >= 0xf8) { // 10xxxxxx // 11111xxx invalid_char_error(&t, c); } else if (c >= 0xc0 && c <= 0xdf) { // 110xxxxx - t.cur_tok->data.char_lit.c = c & 0x1f; - t.remaining_code_units = 1; - t.state = TokenizeStateCharLiteralUnicode; + remaining_code_units = 1; + t.state = TokenizeState_char_literal_unicode; } else if (c >= 0xe0 && c <= 0xef) { // 1110xxxx - t.cur_tok->data.char_lit.c = c & 0x0f; - t.remaining_code_units = 2; - t.state = TokenizeStateCharLiteralUnicode; + remaining_code_units = 2; + t.state = TokenizeState_char_literal_unicode; } else if (c >= 0xf0 && c <= 0xf7) { // 11110xxx - t.cur_tok->data.char_lit.c = c & 0x07; - t.remaining_code_units = 3; - t.state = TokenizeStateCharLiteralUnicode; + remaining_code_units = 3; + t.state = TokenizeState_char_literal_unicode; } else { - t.cur_tok->data.char_lit.c = c; - t.state = TokenizeStateCharLiteralEnd; + t.state = TokenizeState_char_literal_end; } break; - case TokenizeStateCharLiteralEnd: + case TokenizeState_char_literal_backslash: switch (c) { - case '\'': - end_token(&t); - t.state = TokenizeStateStart; - break; - default: - invalid_char_error(&t, c); - } - break; - case TokenizeStateCharLiteralUnicode: - if (c <= 0x7f || c >= 0xc0) { - invalid_char_error(&t, c); - } - t.cur_tok->data.char_lit.c <<= 6; - t.cur_tok->data.char_lit.c += c & 0x3f; - t.remaining_code_units--; - if (t.remaining_code_units == 0) { - t.state = TokenizeStateCharLiteralEnd; - } - break; - case TokenizeStateZero: - switch (c) { - case 'b': - t.radix = 2; - t.state = TokenizeStateNumberNoUnderscore; - break; - case 'o': - t.radix = 8; - t.state = TokenizeStateNumberNoUnderscore; + case 0: + invalid_eof(&t); + goto eof; + case '\n': + case '\r': + tokenize_error(&t, "newline not allowed in character literal"); break; case 'x': - t.radix = 16; - t.state = TokenizeStateNumberNoUnderscore; + t.state = TokenizeState_char_literal_hex_escape; + seen_escape_digits = 0; + break; + case 'u': + t.state = TokenizeState_char_literal_unicode_escape_saw_u; break; default: - // reinterpret as normal number - t.pos -= 1; - t.state = TokenizeStateNumber; - continue; + t.state = TokenizeState_char_literal_end; + break; } break; - case TokenizeStateNumberNoUnderscore: - if (c == '_') { - invalid_char_error(&t, c); - break; - } else if (get_digit_value(c) < t.radix) { - t.is_trailing_underscore = false; - t.state = TokenizeStateNumber; + case TokenizeState_char_literal_hex_escape: + switch (c) { + case ALPHA: + case DIGIT: + seen_escape_digits += 1; + if (seen_escape_digits == 2) { + t.state = TokenizeState_char_literal_end; + } + break; + default: + tokenize_error(&t, "expected hex digit"); + break; } - ZIG_FALLTHROUGH; - case TokenizeStateNumber: - { - if (c == '_') { - t.is_trailing_underscore = true; - t.state = TokenizeStateNumberNoUnderscore; + break; + case TokenizeState_char_literal_unicode_escape_saw_u: + switch (c) { + case '{': + t.state = TokenizeState_char_literal_unicode_escape; + seen_escape_digits = 0; break; - } - if (c == '.') { - if (t.is_trailing_underscore) { - invalid_char_error(&t, c); - break; - } - t.state = TokenizeStateNumberDot; + default: + tokenize_error(&t, "expected '{' to begin unicode escape sequence"); break; - } - if (is_exponent_signifier(c, t.radix)) { - if (t.is_trailing_underscore) { - invalid_char_error(&t, c); - break; - } - if (t.radix != 16 && t.radix != 10) { - invalid_char_error(&t, c); - } - t.state = TokenizeStateFloatExponentUnsigned; - t.radix = 10; // exponent is always base 10 - assert(t.cur_tok->id == TokenIdIntLiteral); - set_token_id(&t, t.cur_tok, TokenIdFloatLiteral); - break; - } - uint32_t digit_value = get_digit_value(c); - if (digit_value >= t.radix) { - if (t.is_trailing_underscore) { - invalid_char_error(&t, c); - break; - } - - if (is_symbol_char(c)) { - invalid_char_error(&t, c); - } - // not my char - t.pos -= 1; - end_token(&t); - t.state = TokenizeStateStart; - continue; - } - BigInt digit_value_bi; - bigint_init_unsigned(&digit_value_bi, digit_value); - - BigInt radix_bi; - bigint_init_unsigned(&radix_bi, t.radix); - - BigInt multiplied; - bigint_mul(&multiplied, &t.cur_tok->data.int_lit.bigint, &radix_bi); - - bigint_add(&t.cur_tok->data.int_lit.bigint, &multiplied, &digit_value_bi); - break; } - case TokenizeStateNumberDot: - { - if (c == '.') { - t.pos -= 2; - end_token(&t); - t.state = TokenizeStateStart; - continue; - } - if (t.radix != 16 && t.radix != 10) { + break; + case TokenizeState_char_literal_unicode_escape: + switch (c) { + case ALPHA: + case DIGIT: + seen_escape_digits += 1; + break; + case '}': + if (seen_escape_digits == 0) { + tokenize_error(&t, "missing unicode escape sequence"); + break; + } + t.state = TokenizeState_char_literal_end; + break; + default: + tokenize_error(&t, "expected hex digit"); + break; + } + break; + case TokenizeState_char_literal_end: + switch (c) { + case '\'': + t.state = TokenizeState_start; + break; + default: invalid_char_error(&t, c); - } - t.pos -= 1; - t.state = TokenizeStateFloatFractionNoUnderscore; - assert(t.cur_tok->id == TokenIdIntLiteral); - set_token_id(&t, t.cur_tok, TokenIdFloatLiteral); - continue; - } - case TokenizeStateFloatFractionNoUnderscore: - if (c == '_') { - invalid_char_error(&t, c); - } else if (get_digit_value(c) < t.radix) { - t.is_trailing_underscore = false; - t.state = TokenizeStateFloatFraction; - } - ZIG_FALLTHROUGH; - case TokenizeStateFloatFraction: - { - if (c == '_') { - t.is_trailing_underscore = true; - t.state = TokenizeStateFloatFractionNoUnderscore; break; - } - if (is_exponent_signifier(c, t.radix)) { - if (t.is_trailing_underscore) { - invalid_char_error(&t, c); - break; - } - t.state = TokenizeStateFloatExponentUnsigned; - t.radix = 10; // exponent is always base 10 - break; - } - uint32_t digit_value = get_digit_value(c); - if (digit_value >= t.radix) { - if (t.is_trailing_underscore) { - invalid_char_error(&t, c); - break; - } - if (is_symbol_char(c)) { - invalid_char_error(&t, c); - } - // not my char - t.pos -= 1; - end_token(&t); - t.state = TokenizeStateStart; - continue; - } - - // we use parse_f128 to generate the float literal, so just - // need to get to the end of the token } break; - case TokenizeStateFloatExponentUnsigned: + case TokenizeState_char_literal_unicode: + if (c >= 0x80 && c <= 0xbf) { + remaining_code_units -= 1; + if (remaining_code_units == 0) { + t.state = TokenizeState_char_literal_end; + } + } else { + invalid_char_error(&t, c); + } + break; + case TokenizeState_multiline_string_literal_line: switch (c) { - case '+': - t.state = TokenizeStateFloatExponentNumberNoUnderscore; - break; - case '-': - t.state = TokenizeStateFloatExponentNumberNoUnderscore; + case 0: + goto eof; + case '\n': + t.state = TokenizeState_start; break; default: - // reinterpret as normal exponent number - t.pos -= 1; - t.state = TokenizeStateFloatExponentNumberNoUnderscore; - continue; - } - break; - case TokenizeStateFloatExponentNumberNoUnderscore: - if (c == '_') { - invalid_char_error(&t, c); - } else if (get_digit_value(c) < t.radix) { - t.is_trailing_underscore = false; - t.state = TokenizeStateFloatExponentNumber; - } - ZIG_FALLTHROUGH; - case TokenizeStateFloatExponentNumber: - { - if (c == '_') { - t.is_trailing_underscore = true; - t.state = TokenizeStateFloatExponentNumberNoUnderscore; break; - } - uint32_t digit_value = get_digit_value(c); - if (digit_value >= t.radix) { - if (t.is_trailing_underscore) { - invalid_char_error(&t, c); - break; - } - if (is_symbol_char(c)) { - invalid_char_error(&t, c); - } - // not my char - t.pos -= 1; - end_token(&t); - t.state = TokenizeStateStart; - continue; - } - - // we use parse_f128 to generate the float literal, so just - // need to get to the end of the token } break; - case TokenizeStateSawDash: + case TokenizeState_bang: switch (c) { + case 0: + goto eof; + case '=': + t.out->ids.last() = TokenIdCmpNotEq; + t.state = TokenizeState_start; + break; + default: + t.state = TokenizeState_start; + continue; + } + break; + case TokenizeState_pipe: + switch (c) { + case 0: + goto eof; + case '=': + t.out->ids.last() = TokenIdBitOrEq; + t.state = TokenizeState_start; + break; + case '|': + t.out->ids.last() = TokenIdBarBar; + t.state = TokenizeState_start; + break; + default: + t.state = TokenizeState_start; + continue; + } + break; + case TokenizeState_equal: + switch (c) { + case 0: + goto eof; + case '=': + t.out->ids.last() = TokenIdCmpEq; + t.state = TokenizeState_start; + break; case '>': - set_token_id(&t, t.cur_tok, TokenIdArrow); - end_token(&t); - t.state = TokenizeStateStart; + t.out->ids.last() = TokenIdFatArrow; + t.state = TokenizeState_start; + break; + default: + t.state = TokenizeState_start; + continue; + } + break; + case TokenizeState_minus: + switch (c) { + case 0: + goto eof; + case '>': + t.out->ids.last() = TokenIdArrow; + t.state = TokenizeState_start; break; case '=': - set_token_id(&t, t.cur_tok, TokenIdMinusEq); - end_token(&t); - t.state = TokenizeStateStart; + t.out->ids.last() = TokenIdMinusEq; + t.state = TokenizeState_start; break; case '%': - set_token_id(&t, t.cur_tok, TokenIdMinusPercent); - t.state = TokenizeStateSawMinusPercent; + t.state = TokenizeState_minus_percent; break; default: - t.pos -= 1; - end_token(&t); - t.state = TokenizeStateStart; + t.state = TokenizeState_start; continue; } break; - case TokenizeStateSawMinusPercent: + case TokenizeState_minus_percent: switch (c) { + case 0: + t.out->ids.last() = TokenIdMinusPercent; + goto eof; case '=': - set_token_id(&t, t.cur_tok, TokenIdMinusPercentEq); - end_token(&t); - t.state = TokenizeStateStart; + t.out->ids.last() = TokenIdMinusPercentEq; + t.state = TokenizeState_start; break; default: + t.out->ids.last() = TokenIdMinusPercent; + t.state = TokenizeState_start; + continue; + } + break; + case TokenizeState_angle_bracket_left: + switch (c) { + case 0: + goto eof; + case '=': + t.out->ids.last() = TokenIdCmpLessOrEq; + t.state = TokenizeState_start; + break; + case '<': + t.state = TokenizeState_angle_bracket_angle_bracket_left; + break; + default: + t.state = TokenizeState_start; + continue; + } + break; + case TokenizeState_angle_bracket_angle_bracket_left: + switch (c) { + case 0: + t.out->ids.last() = TokenIdBitShiftLeft; + goto eof; + case '=': + t.out->ids.last() = TokenIdBitShiftLeftEq; + t.state = TokenizeState_start; + break; + default: + t.out->ids.last() = TokenIdBitShiftLeft; + t.state = TokenizeState_start; + continue; + } + break; + case TokenizeState_angle_bracket_right: + switch (c) { + case 0: + goto eof; + case '=': + t.out->ids.last() = TokenIdCmpGreaterOrEq; + t.state = TokenizeState_start; + break; + case '>': + t.state = TokenizeState_angle_bracket_angle_bracket_right; + break; + default: + t.state = TokenizeState_start; + continue; + } + break; + case TokenizeState_angle_bracket_angle_bracket_right: + switch (c) { + case 0: + t.out->ids.last() = TokenIdBitShiftRight; + goto eof; + case '=': + t.out->ids.last() = TokenIdBitShiftRightEq; + t.state = TokenizeState_start; + break; + default: + t.out->ids.last() = TokenIdBitShiftRight; + t.state = TokenizeState_start; + continue; + } + break; + case TokenizeState_period: + switch (c) { + case 0: + goto eof; + case '.': + t.state = TokenizeState_period_2; + break; + case '*': + t.state = TokenizeState_period_asterisk; + break; + default: + t.state = TokenizeState_start; + continue; + } + break; + case TokenizeState_period_2: + switch (c) { + case 0: + t.out->ids.last() = TokenIdEllipsis2; + goto eof; + case '.': + t.out->ids.last() = TokenIdEllipsis3; + t.state = TokenizeState_start; + break; + default: + t.out->ids.last() = TokenIdEllipsis2; + t.state = TokenizeState_start; + continue; + } + break; + case TokenizeState_period_asterisk: + switch (c) { + case 0: + t.out->ids.last() = TokenIdDotStar; + goto eof; + case '*': + tokenize_error(&t, "`.*` cannot be followed by `*`. Are you missing a space?"); + break; + default: + t.out->ids.last() = TokenIdDotStar; + t.state = TokenizeState_start; + continue; + } + break; + case TokenizeState_slash: + switch (c) { + case 0: + goto eof; + case '/': + t.state = TokenizeState_line_comment_start; + break; + case '=': + t.out->ids.last() = TokenIdDivEq; + t.state = TokenizeState_start; + break; + default: + t.state = TokenizeState_start; + continue; + } + break; + case TokenizeState_line_comment_start: + switch (c) { + case 0: + goto eof; + case '/': + t.state = TokenizeState_doc_comment_start; + break; + case '!': + t.out->ids.last() = TokenIdContainerDocComment; + t.state = TokenizeState_container_doc_comment; + break; + case '\n': + cancel_token(&t); + t.state = TokenizeState_start; + break; + default: + cancel_token(&t); + t.state = TokenizeState_line_comment; + break; + } + break; + case TokenizeState_doc_comment_start: + switch (c) { + case 0: + t.out->ids.last() = TokenIdDocComment; + goto eof; + case '/': + cancel_token(&t); + t.state = TokenizeState_line_comment; + break; + case '\n': + t.out->ids.last() = TokenIdDocComment; + t.state = TokenizeState_start; + break; + default: + t.out->ids.last() = TokenIdDocComment; + t.state = TokenizeState_doc_comment; + break; + } + break; + case TokenizeState_line_comment: + switch (c) { + case 0: + goto eof; + case '\n': + t.state = TokenizeState_start; + break; + default: + break; + } + break; + case TokenizeState_doc_comment: + case TokenizeState_container_doc_comment: + switch (c) { + case 0: + goto eof; + case '\n': + t.state = TokenizeState_start; + break; + default: + // do nothing + break; + } + break; + case TokenizeState_zero: + switch (c) { + case 0: + goto eof; + case 'b': + t.state = TokenizeState_int_literal_bin_no_underscore; + break; + case 'o': + t.state = TokenizeState_int_literal_oct_no_underscore; + break; + case 'x': + t.state = TokenizeState_int_literal_hex_no_underscore; + break; + case DIGIT: + case '_': + case '.': + case 'e': + case 'E': + // Reinterpret as a decimal number. + t.state = TokenizeState_int_literal_dec; + continue; + case ALPHA_EXCEPT_E_B_O_X: + invalid_char_error(&t, c); + break; + default: + t.state = TokenizeState_start; + continue; + } + break; + case TokenizeState_int_literal_bin_no_underscore: + switch (c) { + case '0': + case '1': + t.state = TokenizeState_int_literal_bin; + break; + default: + invalid_char_error(&t, c); + } + break; + case TokenizeState_int_literal_bin: + switch (c) { + case 0: + goto eof; + case '_': + t.state = TokenizeState_int_literal_bin_no_underscore; + break; + case '0': + case '1': + break; + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case ALPHA: + invalid_char_error(&t, c); + break; + default: + t.state = TokenizeState_start; + continue; + } + break; + case TokenizeState_int_literal_oct_no_underscore: + switch (c) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + t.state = TokenizeState_int_literal_oct; + break; + default: + invalid_char_error(&t, c); + break; + } + break; + case TokenizeState_int_literal_oct: + switch (c) { + case 0: + goto eof; + case '_': + t.state = TokenizeState_int_literal_oct_no_underscore; + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + break; + case ALPHA: + case '8': + case '9': + invalid_char_error(&t, c); + break; + default: + t.state = TokenizeState_start; + continue; + } + break; + case TokenizeState_int_literal_dec_no_underscore: + switch (c) { + case DIGIT: + t.state = TokenizeState_int_literal_dec; + break; + default: + invalid_char_error(&t, c); + break; + } + break; + case TokenizeState_int_literal_dec: + switch (c) { + case 0: + goto eof; + case '_': + t.state = TokenizeState_int_literal_dec_no_underscore; + break; + case '.': + t.state = TokenizeState_num_dot_dec; + t.out->ids.last() = TokenIdFloatLiteral; + break; + case 'e': + case 'E': + t.state = TokenizeState_float_exponent_unsigned; + t.out->ids.last() = TokenIdFloatLiteral; + break; + case DIGIT: + break; + case ALPHA_EXCEPT_E: + invalid_char_error(&t, c); + break; + default: + t.state = TokenizeState_start; + continue; + } + break; + case TokenizeState_int_literal_hex_no_underscore: + switch (c) { + case HEXDIGIT: + t.state = TokenizeState_int_literal_hex; + break; + default: + invalid_char_error(&t, c); + } + break; + case TokenizeState_int_literal_hex: + switch (c) { + case 0: + goto eof; + case '_': + t.state = TokenizeState_int_literal_hex_no_underscore; + break; + case '.': + t.state = TokenizeState_num_dot_hex; + t.out->ids.last() = TokenIdFloatLiteral; + break; + case 'p': + case 'P': + t.state = TokenizeState_float_exponent_unsigned; + t.out->ids.last() = TokenIdFloatLiteral; + break; + case HEXDIGIT: + break; + case ALPHA_EXCEPT_HEX_AND_P: + invalid_char_error(&t, c); + break; + default: + t.state = TokenizeState_start; + continue; + } + break; + case TokenizeState_num_dot_dec: + switch (c) { + case 0: + goto eof; + case '.': + t.out->ids.last() = TokenIdIntLiteral; t.pos -= 1; - end_token(&t); - t.state = TokenizeStateStart; + t.column -= 1; + t.state = TokenizeState_start; + continue; + case 'e': + case 'E': + t.state = TokenizeState_float_exponent_unsigned; + break; + case DIGIT: + t.state = TokenizeState_float_fraction_dec; + break; + case ALPHA_EXCEPT_E: + invalid_char_error(&t, c); + break; + default: + t.state = TokenizeState_start; + continue; + } + break; + case TokenizeState_num_dot_hex: + switch (c) { + case 0: + goto eof; + case '.': + t.out->ids.last() = TokenIdIntLiteral; + t.pos -= 1; + t.column -= 1; + t.state = TokenizeState_start; + continue; + case 'p': + case 'P': + t.state = TokenizeState_float_exponent_unsigned; + break; + case HEXDIGIT: + t.out->ids.last() = TokenIdFloatLiteral; + t.state = TokenizeState_float_fraction_hex; + break; + case ALPHA_EXCEPT_HEX_AND_P: + invalid_char_error(&t, c); + break; + default: + t.state = TokenizeState_start; + continue; + } + break; + case TokenizeState_float_fraction_dec_no_underscore: + switch (c) { + case DIGIT: + t.state = TokenizeState_float_fraction_dec; + break; + default: + invalid_char_error(&t, c); + } + break; + case TokenizeState_float_fraction_dec: + switch (c) { + case 0: + goto eof; + case '_': + t.state = TokenizeState_float_fraction_dec_no_underscore; + break; + case 'e': + case 'E': + t.state = TokenizeState_float_exponent_unsigned; + break; + case DIGIT: + break; + case ALPHA_EXCEPT_E: + invalid_char_error(&t, c); + break; + default: + t.state = TokenizeState_start; + continue; + } + break; + case TokenizeState_float_fraction_hex_no_underscore: + switch (c) { + case HEXDIGIT: + t.state = TokenizeState_float_fraction_hex; + break; + default: + invalid_char_error(&t, c); + } + break; + case TokenizeState_float_fraction_hex: + switch (c) { + case 0: + goto eof; + case '_': + t.state = TokenizeState_float_fraction_hex_no_underscore; + break; + case 'p': + case 'P': + t.state = TokenizeState_float_exponent_unsigned; + break; + case HEXDIGIT: + break; + case ALPHA_EXCEPT_HEX_AND_P: + invalid_char_error(&t, c); + break; + default: + t.state = TokenizeState_start; + continue; + } + break; + case TokenizeState_float_exponent_unsigned: + switch (c) { + case '+': + case '-': + t.state = TokenizeState_float_exponent_num_no_underscore; + break; + default: + // Reinterpret as a normal exponent number. + t.state = TokenizeState_float_exponent_num_no_underscore; + continue; + } + break; + case TokenizeState_float_exponent_num_no_underscore: + switch (c) { + case DIGIT: + t.state = TokenizeState_float_exponent_num; + break; + default: + invalid_char_error(&t, c); + } + break; + case TokenizeState_float_exponent_num: + switch (c) { + case 0: + goto eof; + case '_': + t.state = TokenizeState_float_exponent_num_no_underscore; + break; + case DIGIT: + break; + case ALPHA: + invalid_char_error(&t, c); + break; + default: + t.state = TokenizeState_start; continue; } break; } + t.pos += 1; if (c == '\n') { - out->line_offsets->append(t.pos + 1); t.line += 1; t.column = 0; } else { t.column += 1; } } - // EOF - switch (t.state) { - case TokenizeStateStart: - case TokenizeStateError: - break; - case TokenizeStateNumberNoUnderscore: - case TokenizeStateFloatFractionNoUnderscore: - case TokenizeStateFloatExponentNumberNoUnderscore: - case TokenizeStateNumberDot: - tokenize_error(&t, "unterminated number literal"); - break; - case TokenizeStateString: - tokenize_error(&t, "unterminated string"); - break; - case TokenizeStateStringEscape: - case TokenizeStateStringEscapeUnicodeStart: - case TokenizeStateCharCode: - if (t.cur_tok->id == TokenIdStringLiteral) { - tokenize_error(&t, "unterminated string"); - break; - } else if (t.cur_tok->id == TokenIdCharLiteral) { - tokenize_error(&t, "unterminated Unicode code point literal"); - break; - } else { - zig_unreachable(); - } - break; - case TokenizeStateCharLiteral: - case TokenizeStateCharLiteralEnd: - case TokenizeStateCharLiteralUnicode: - tokenize_error(&t, "unterminated Unicode code point literal"); - break; - case TokenizeStateSymbol: - case TokenizeStateZero: - case TokenizeStateNumber: - case TokenizeStateFloatFraction: - case TokenizeStateFloatExponentUnsigned: - case TokenizeStateFloatExponentNumber: - case TokenizeStateSawStar: - case TokenizeStateSawSlash: - case TokenizeStateSawPercent: - case TokenizeStateSawPlus: - case TokenizeStateSawDash: - case TokenizeStateSawAmpersand: - case TokenizeStateSawCaret: - case TokenizeStateSawBar: - case TokenizeStateSawEq: - case TokenizeStateSawBang: - case TokenizeStateSawLessThan: - case TokenizeStateSawLessThanLessThan: - case TokenizeStateSawGreaterThan: - case TokenizeStateSawGreaterThanGreaterThan: - case TokenizeStateSawDot: - case TokenizeStateSawDotStar: - case TokenizeStateSawAtSign: - case TokenizeStateSawStarPercent: - case TokenizeStateSawPlusPercent: - case TokenizeStateSawMinusPercent: - case TokenizeStateLineString: - case TokenizeStateLineStringEnd: - case TokenizeStateDocComment: - case TokenizeStateContainerDocComment: - end_token(&t); - break; - case TokenizeStateSawDotDot: - case TokenizeStateSawBackslash: - case TokenizeStateLineStringContinue: - tokenize_error(&t, "unexpected EOF"); - break; - case TokenizeStateLineComment: - break; - case TokenizeStateSawSlash2: - cancel_token(&t); - break; - case TokenizeStateSawSlash3: - set_token_id(&t, t.cur_tok, TokenIdDocComment); - end_token(&t); - break; - case TokenizeStateSawSlashBang: - set_token_id(&t, t.cur_tok, TokenIdContainerDocComment); - end_token(&t); - break; - } - if (t.state != TokenizeStateError) { - if (t.tokens->length > 0) { - Token *last_token = &t.tokens->last(); - t.line = (int)last_token->start_line; - t.column = (int)last_token->start_column; - t.pos = last_token->start_pos; - } else { - t.pos = 0; - } - begin_token(&t, TokenIdEof); - end_token(&t); - assert(!t.cur_tok); - } +eof:; + + begin_token(&t, TokenIdEof); } const char * token_name(TokenId id) { switch (id) { case TokenIdAmpersand: return "&"; case TokenIdArrow: return "->"; - case TokenIdAtSign: return "@"; case TokenIdBang: return "!"; case TokenIdBarBar: return "||"; case TokenIdBinOr: return "|"; @@ -1622,9 +1533,7 @@ const char * token_name(TokenId id) { case TokenIdMinusPercent: return "-%"; case TokenIdMinusPercentEq: return "-%="; case TokenIdModEq: return "%="; - case TokenIdNumberSign: return "#"; case TokenIdPercent: return "%"; - case TokenIdPercentDot: return "%."; case TokenIdPlus: return "+"; case TokenIdPlusEq: return "+="; case TokenIdPlusPercent: return "+%"; @@ -1638,33 +1547,15 @@ const char * token_name(TokenId id) { case TokenIdStar: return "*"; case TokenIdStarStar: return "**"; case TokenIdStringLiteral: return "StringLiteral"; - case TokenIdMultilineStringLiteral: return "MultilineStringLiteral"; - case TokenIdSymbol: return "Symbol"; + case TokenIdMultilineStringLiteralLine: return "MultilineStringLiteralLine"; + case TokenIdIdentifier: return "Identifier"; case TokenIdTilde: return "~"; case TokenIdTimesEq: return "*="; case TokenIdTimesPercent: return "*%"; case TokenIdTimesPercentEq: return "*%="; + case TokenIdBuiltin: return "Builtin"; case TokenIdCount: zig_unreachable(); } return "(invalid token)"; } - -void print_tokens(Buf *buf, ZigList *tokens) { - for (size_t i = 0; i < tokens->length; i += 1) { - Token *token = &tokens->at(i); - fprintf(stderr, "%s ", token_name(token->id)); - if (token->start_pos != SIZE_MAX) { - fwrite(buf_ptr(buf) + token->start_pos, 1, token->end_pos - token->start_pos, stderr); - } - fprintf(stderr, "\n"); - } -} - -bool valid_symbol_starter(uint8_t c) { - switch (c) { - case SYMBOL_START: - return true; - } - return false; -} diff --git a/src/stage1/tokenizer.hpp b/src/stage1/tokenizer.hpp index 2bb673c8f3..0e196597eb 100644 --- a/src/stage1/tokenizer.hpp +++ b/src/stage1/tokenizer.hpp @@ -12,10 +12,9 @@ #include "bigint.hpp" #include "bigfloat.hpp" -enum TokenId { +enum TokenId : uint8_t { TokenIdAmpersand, TokenIdArrow, - TokenIdAtSign, TokenIdBang, TokenIdBarBar, TokenIdBinOr, @@ -27,6 +26,7 @@ enum TokenId { TokenIdBitShiftRight, TokenIdBitShiftRightEq, TokenIdBitXorEq, + TokenIdBuiltin, TokenIdCharLiteral, TokenIdCmpEq, TokenIdCmpGreaterOrEq, @@ -109,9 +109,7 @@ enum TokenId { TokenIdMinusPercent, TokenIdMinusPercentEq, TokenIdModEq, - TokenIdNumberSign, TokenIdPercent, - TokenIdPercentDot, TokenIdPlus, TokenIdPlusEq, TokenIdPlusPercent, @@ -125,75 +123,35 @@ enum TokenId { TokenIdStar, TokenIdStarStar, TokenIdStringLiteral, - TokenIdMultilineStringLiteral, - TokenIdSymbol, + TokenIdMultilineStringLiteralLine, + TokenIdIdentifier, TokenIdTilde, TokenIdTimesEq, TokenIdTimesPercent, TokenIdTimesPercentEq, + TokenIdCount, }; -struct TokenFloatLit { - BigFloat bigfloat; - // overflow is true if when parsing the number, we discovered it would not fit - // without losing data - bool overflow; +typedef uint32_t TokenIndex; + +struct TokenLoc { + uint32_t offset; + uint32_t line; + uint32_t column; }; -struct TokenIntLit { - BigInt bigint; -}; - -struct TokenStrLit { - Buf str; -}; - -struct TokenCharLit { - uint32_t c; -}; - -struct Token { - TokenId id; - size_t start_pos; - size_t end_pos; - size_t start_line; - size_t start_column; - - union { - // TokenIdIntLiteral - TokenIntLit int_lit; - - // TokenIdFloatLiteral - TokenFloatLit float_lit; - - // TokenIdStringLiteral, TokenIdMultilineStringLiteral or TokenIdSymbol - TokenStrLit str_lit; - - // TokenIdCharLiteral - TokenCharLit char_lit; - } data; -}; -// work around conflicting name Token which is also found in libclang -typedef Token ZigToken; - struct Tokenization { - ZigList *tokens; - ZigList *line_offsets; + ZigList ids; + ZigList locs; // if an error occurred Buf *err; - size_t err_line; - size_t err_column; + uint32_t err_byte_offset; }; -void tokenize(Buf *buf, Tokenization *out_tokenization); - -void print_tokens(Buf *buf, ZigList *tokens); +void tokenize(const char *source, Tokenization *out_tokenization); const char * token_name(TokenId id); -bool valid_symbol_starter(uint8_t c); -bool is_zig_keyword(Buf *buf); - #endif diff --git a/test/behavior/misc.zig b/test/behavior/misc.zig index 0300afcdea..e010644756 100644 --- a/test/behavior/misc.zig +++ b/test/behavior/misc.zig @@ -1,6 +1,7 @@ const std = @import("std"); const expect = std.testing.expect; const expectEqualSlices = std.testing.expectEqualSlices; +const expectEqualStrings = std.testing.expectEqualStrings; const mem = std.mem; const builtin = @import("builtin"); @@ -147,13 +148,13 @@ test "array mult operator" { } test "string escapes" { - try expect(mem.eql(u8, "\"", "\x22")); - try expect(mem.eql(u8, "\'", "\x27")); - try expect(mem.eql(u8, "\n", "\x0a")); - try expect(mem.eql(u8, "\r", "\x0d")); - try expect(mem.eql(u8, "\t", "\x09")); - try expect(mem.eql(u8, "\\", "\x5c")); - try expect(mem.eql(u8, "\u{1234}\u{069}\u{1}", "\xe1\x88\xb4\x69\x01")); + try expectEqualStrings("\"", "\x22"); + try expectEqualStrings("\'", "\x27"); + try expectEqualStrings("\n", "\x0a"); + try expectEqualStrings("\r", "\x0d"); + try expectEqualStrings("\t", "\x09"); + try expectEqualStrings("\\", "\x5c"); + try expectEqualStrings("\u{1234}\u{069}\u{1}", "\xe1\x88\xb4\x69\x01"); } test "multiline string" { From eb37722d79a2cde636c80d35c9478139d8513931 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 27 May 2021 17:39:18 -0700 Subject: [PATCH 02/14] lol that's never going to happen in stage1 --- src/stage1/all_types.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/stage1/all_types.hpp b/src/stage1/all_types.hpp index ad7a8cd5cb..1734490458 100644 --- a/src/stage1/all_types.hpp +++ b/src/stage1/all_types.hpp @@ -2720,8 +2720,7 @@ enum IrInstGenId { IrInstGenIdExtern, }; -// Common fields between IrInstSrc and IrInstGen. This allows future passes -// after pass2 to be added to zig. +// Common fields between IrInstSrc and IrInstGen. struct IrInst { // if ref_count is zero and the instruction has no side effects, // the instruction can be omitted in codegen From e072ace436e3bfda18cde71492380f863e51cc61 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 27 May 2021 17:57:14 -0700 Subject: [PATCH 03/14] stage1: rename IrExecutableSrc to Stage1Zir and make IrBuilderSrc private to astgen.cpp --- src/stage1/all_types.hpp | 6 +- src/stage1/analyze.cpp | 4 +- src/stage1/astgen.cpp | 29 ++++++---- src/stage1/astgen.hpp | 15 ++--- src/stage1/ir.cpp | 118 +++++++++++++++++++-------------------- src/stage1/ir.hpp | 2 +- src/stage1/ir_print.cpp | 2 +- src/stage1/ir_print.hpp | 2 +- 8 files changed, 89 insertions(+), 89 deletions(-) diff --git a/src/stage1/all_types.hpp b/src/stage1/all_types.hpp index 1734490458..f27168ca2f 100644 --- a/src/stage1/all_types.hpp +++ b/src/stage1/all_types.hpp @@ -110,7 +110,7 @@ enum X64CABIClass { X64CABIClass_SSE, }; -struct IrExecutableSrc { +struct Stage1Zir { ZigList basic_block_list; Buf *name; ZigFn *name_fn; @@ -148,7 +148,7 @@ struct IrExecutableGen { Buf *c_import_buf; AstNode *source_node; IrExecutableGen *parent_exec; - IrExecutableSrc *source_exec; + Stage1Zir *source_exec; Scope *begin_scope; ErrorMsg *first_err_trace_msg; ZigList tld_list; @@ -1651,7 +1651,7 @@ struct ZigFn { // in the case of async functions this is the implicit return type according to the // zig source code, not according to zig ir ZigType *src_implicit_return_type; - IrExecutableSrc *ir_executable; + Stage1Zir *ir_executable; IrExecutableGen analyzed_executable; size_t prealloc_bbc; size_t prealloc_backward_branch_quota; diff --git a/src/stage1/analyze.cpp b/src/stage1/analyze.cpp index b675beb9e0..fa53fae075 100644 --- a/src/stage1/analyze.cpp +++ b/src/stage1/analyze.cpp @@ -3653,7 +3653,7 @@ static void get_fully_qualified_decl_name(CodeGen *g, Buf *buf, Tld *tld, bool i static ZigFn *create_fn_raw(CodeGen *g, bool is_noinline) { ZigFn *fn_entry = heap::c_allocator.create(); - fn_entry->ir_executable = heap::c_allocator.create(); + fn_entry->ir_executable = heap::c_allocator.create(); fn_entry->prealloc_backward_branch_quota = default_backward_branch_quota; @@ -9862,7 +9862,7 @@ void AstNode::src() { line, column); } -void IrExecutableSrc::src() { +void Stage1Zir::src() { if (this->source_node != nullptr) { this->source_node->src(); } diff --git a/src/stage1/astgen.cpp b/src/stage1/astgen.cpp index 94ade4bebc..3dd4e39dcb 100644 --- a/src/stage1/astgen.cpp +++ b/src/stage1/astgen.cpp @@ -11,6 +11,13 @@ #include "os.hpp" #include "parser.hpp" +struct IrBuilderSrc { + CodeGen *codegen; + Stage1Zir *exec; + IrBasicBlockSrc *current_basic_block; + AstNode *main_block_node; +}; + static IrInstSrc *ir_gen_node(IrBuilderSrc *irb, AstNode *node, Scope *scope); static IrInstSrc *ir_gen_node_extra(IrBuilderSrc *irb, AstNode *node, Scope *scope, LVal lval, ResultLoc *result_loc); @@ -34,14 +41,14 @@ static void ir_assert_impl(bool ok, IrInst *source_instruction, char const *file src_assert_impl(ok, source_instruction->source_node, file, line); } -static void ir_add_call_stack_errors(CodeGen *codegen, IrExecutableSrc *exec, ErrorMsg *err_msg, int limit) { +static void ir_add_call_stack_errors(CodeGen *codegen, Stage1Zir *exec, ErrorMsg *err_msg, int limit) { if (!exec || !exec->source_node || limit < 0) return; add_error_note(codegen, err_msg, exec->source_node, buf_sprintf("called from here")); ir_add_call_stack_errors_gen(codegen, exec->parent_exec, err_msg, limit - 1); } -static ErrorMsg *exec_add_error_node(CodeGen *codegen, IrExecutableSrc *exec, AstNode *source_node, Buf *msg) { +static ErrorMsg *exec_add_error_node(CodeGen *codegen, Stage1Zir *exec, AstNode *source_node, Buf *msg) { ErrorMsg *err_msg = add_node_error(codegen, source_node, msg); invalidate_exec(exec, err_msg); if (exec->parent_exec) { @@ -342,7 +349,7 @@ void destroy_instruction_src(IrInstSrc *inst) { } -bool ir_should_inline(IrExecutableSrc *exec, Scope *scope) { +bool ir_should_inline(Stage1Zir *exec, Scope *scope) { if (exec->is_inline) return true; @@ -364,17 +371,17 @@ static void ir_instruction_append(IrBasicBlockSrc *basic_block, IrInstSrc *instr basic_block->instruction_list.append(instruction); } -static size_t exec_next_debug_id(IrExecutableSrc *exec) { +static size_t exec_next_debug_id(Stage1Zir *exec) { size_t result = exec->next_debug_id; exec->next_debug_id += 1; return result; } -static ZigFn *exec_fn_entry(IrExecutableSrc *exec) { +static ZigFn *exec_fn_entry(Stage1Zir *exec) { return exec->fn_entry; } -static Buf *exec_c_import_buf(IrExecutableSrc *exec) { +static Buf *exec_c_import_buf(Stage1Zir *exec) { return exec->c_import_buf; } @@ -5891,7 +5898,7 @@ static IrInstSrc *ir_gen_var_decl(IrBuilderSrc *irb, Scope *scope, AstNode *node Scope *init_scope = is_comptime_scalar ? create_comptime_scope(irb->codegen, variable_declaration->expr, scope) : scope; - // Temporarily set the name of the IrExecutableSrc to the VariableDeclaration + // Temporarily set the name of the Stage1Zir to the VariableDeclaration // so that the struct or enum from the init expression inherits the name. Buf *old_exec_name = irb->exec->name; irb->exec->name = variable_declaration->symbol; @@ -7511,7 +7518,7 @@ static bool render_instance_name_recursive(CodeGen *codegen, Buf *name, Scope *o return true; } -Buf *get_anon_type_name(CodeGen *codegen, IrExecutableSrc *exec, const char *kind_name, +Buf *get_anon_type_name(CodeGen *codegen, Stage1Zir *exec, const char *kind_name, Scope *scope, AstNode *source_node, Buf *out_bare_name) { if (exec != nullptr && exec->name) { @@ -8040,7 +8047,7 @@ static IrInstSrc *ir_gen_node(IrBuilderSrc *irb, AstNode *node, Scope *scope) { return ir_gen_node_extra(irb, node, scope, LValNone, nullptr); } -bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutableSrc *ir_executable) { +bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, Stage1Zir *ir_executable) { assert(node->owner); IrBuilderSrc ir_builder = {0}; @@ -8081,7 +8088,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutableSrc *ir_e bool ir_gen_fn(CodeGen *codegen, ZigFn *fn_entry) { assert(fn_entry); - IrExecutableSrc *ir_executable = fn_entry->ir_executable; + Stage1Zir *ir_executable = fn_entry->ir_executable; AstNode *body_node = fn_entry->body_node; assert(fn_entry->child_scope); @@ -8089,7 +8096,7 @@ bool ir_gen_fn(CodeGen *codegen, ZigFn *fn_entry) { return ir_gen(codegen, body_node, fn_entry->child_scope, ir_executable); } -void invalidate_exec(IrExecutableSrc *exec, ErrorMsg *msg) { +void invalidate_exec(Stage1Zir *exec, ErrorMsg *msg) { if (exec->first_err_trace_msg != nullptr) return; diff --git a/src/stage1/astgen.hpp b/src/stage1/astgen.hpp index c3750aac98..9b78b2496b 100644 --- a/src/stage1/astgen.hpp +++ b/src/stage1/astgen.hpp @@ -10,7 +10,7 @@ #include "all_types.hpp" -bool ir_gen(CodeGen *g, AstNode *node, Scope *scope, IrExecutableSrc *ir_executable); +bool ir_gen(CodeGen *g, AstNode *node, Scope *scope, Stage1Zir *ir_executable); bool ir_gen_fn(CodeGen *g, ZigFn *fn_entry); bool ir_inst_src_has_side_effects(IrInstSrc *inst); @@ -21,7 +21,7 @@ ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_scope, ResultLoc *no_result_loc(void); -void invalidate_exec(IrExecutableSrc *exec, ErrorMsg *msg); +void invalidate_exec(Stage1Zir *exec, ErrorMsg *msg); AstNode *ast_field_to_symbol_node(AstNode *err_set_field_node); void ir_add_call_stack_errors_gen(CodeGen *codegen, IrExecutableGen *exec, ErrorMsg *err_msg, @@ -29,15 +29,8 @@ void ir_add_call_stack_errors_gen(CodeGen *codegen, IrExecutableGen *exec, Error void destroy_instruction_src(IrInstSrc *inst); -struct IrBuilderSrc { - CodeGen *codegen; - IrExecutableSrc *exec; - IrBasicBlockSrc *current_basic_block; - AstNode *main_block_node; -}; - -bool ir_should_inline(IrExecutableSrc *exec, Scope *scope); -Buf *get_anon_type_name(CodeGen *codegen, IrExecutableSrc *exec, const char *kind_name, +bool ir_should_inline(Stage1Zir *exec, Scope *scope); +Buf *get_anon_type_name(CodeGen *codegen, Stage1Zir *exec, const char *kind_name, Scope *scope, AstNode *source_node, Buf *out_bare_name); #endif diff --git a/src/stage1/ir.cpp b/src/stage1/ir.cpp index 4070372a12..f143c101a0 100644 --- a/src/stage1/ir.cpp +++ b/src/stage1/ir.cpp @@ -33,7 +33,8 @@ struct IrBuilderGen { struct IrAnalyze { CodeGen *codegen; - IrBuilderSrc old_irb; + Stage1Zir *zir; + IrBasicBlockSrc *zir_current_basic_block; IrBuilderGen new_irb; size_t old_bb_index; size_t instruction_index; @@ -476,17 +477,17 @@ static void ira_deref(IrAnalyze *ira) { } assert(ira->ref_count != 0); - for (size_t bb_i = 0; bb_i < ira->old_irb.exec->basic_block_list.length; bb_i += 1) { - IrBasicBlockSrc *pass1_bb = ira->old_irb.exec->basic_block_list.items[bb_i]; + for (size_t bb_i = 0; bb_i < ira->zir->basic_block_list.length; bb_i += 1) { + IrBasicBlockSrc *pass1_bb = ira->zir->basic_block_list.items[bb_i]; for (size_t inst_i = 0; inst_i < pass1_bb->instruction_list.length; inst_i += 1) { IrInstSrc *pass1_inst = pass1_bb->instruction_list.items[inst_i]; destroy_instruction_src(pass1_inst); } heap::c_allocator.destroy(pass1_bb); } - ira->old_irb.exec->basic_block_list.deinit(); - ira->old_irb.exec->tld_list.deinit(); - heap::c_allocator.destroy(ira->old_irb.exec); + ira->zir->basic_block_list.deinit(); + ira->zir->tld_list.deinit(); + heap::c_allocator.destroy(ira->zir); ira->src_implicit_return_type_list.deinit(); ira->resume_stack.deinit(); @@ -2630,7 +2631,7 @@ static Error ir_exec_scan_for_side_effects(CodeGen *codegen, IrExecutableGen *ex } static bool ir_emit_global_runtime_side_effect(IrAnalyze *ira, IrInst* source_instruction) { - if (ir_should_inline(ira->old_irb.exec, source_instruction->scope)) { + if (ir_should_inline(ira->zir, source_instruction->scope)) { ir_add_error(ira, source_instruction, buf_sprintf("unable to evaluate constant expression")); return false; } @@ -5287,7 +5288,7 @@ static IrBasicBlockGen *ir_get_new_bb_runtime(IrAnalyze *ira, IrBasicBlockSrc *o static void ir_start_bb(IrAnalyze *ira, IrBasicBlockSrc *old_bb, IrBasicBlockSrc *const_predecessor_bb) { ir_assert(!old_bb->suspended, (old_bb->instruction_list.length != 0) ? &old_bb->instruction_list.at(0)->base : nullptr); ira->instruction_index = 0; - ira->old_irb.current_basic_block = old_bb; + ira->zir_current_basic_block = old_bb; ira->const_predecessor_bb = const_predecessor_bb; ira->old_bb_index = old_bb->index; } @@ -5297,23 +5298,23 @@ static IrInstGen *ira_suspend(IrAnalyze *ira, IrInst *old_instruction, IrBasicBl { if (ira->codegen->verbose_ir) { fprintf(stderr, "suspend %s_%" PRIu32 " %s_%" PRIu32 " #%" PRIu32 " (%zu,%zu)\n", - ira->old_irb.current_basic_block->name_hint, - ira->old_irb.current_basic_block->debug_id, - ira->old_irb.exec->basic_block_list.at(ira->old_bb_index)->name_hint, - ira->old_irb.exec->basic_block_list.at(ira->old_bb_index)->debug_id, - ira->old_irb.current_basic_block->instruction_list.at(ira->instruction_index)->base.debug_id, + ira->zir_current_basic_block->name_hint, + ira->zir_current_basic_block->debug_id, + ira->zir->basic_block_list.at(ira->old_bb_index)->name_hint, + ira->zir->basic_block_list.at(ira->old_bb_index)->debug_id, + ira->zir_current_basic_block->instruction_list.at(ira->instruction_index)->base.debug_id, ira->old_bb_index, ira->instruction_index); } suspend_pos->basic_block_index = ira->old_bb_index; suspend_pos->instruction_index = ira->instruction_index; - ira->old_irb.current_basic_block->suspended = true; + ira->zir_current_basic_block->suspended = true; // null next_bb means that the caller plans to call ira_resume before returning if (next_bb != nullptr) { ira->old_bb_index = next_bb->index; - ira->old_irb.current_basic_block = ira->old_irb.exec->basic_block_list.at(ira->old_bb_index); - assert(ira->old_irb.current_basic_block == next_bb); + ira->zir_current_basic_block = ira->zir->basic_block_list.at(ira->old_bb_index); + assert(ira->zir_current_basic_block == next_bb); ira->instruction_index = 0; ira->const_predecessor_bb = nullptr; next_bb->child = ir_get_new_bb_runtime(ira, next_bb, old_instruction); @@ -5328,19 +5329,19 @@ static IrInstGen *ira_resume(IrAnalyze *ira) { fprintf(stderr, "resume (%zu,%zu) ", pos.basic_block_index, pos.instruction_index); } ira->old_bb_index = pos.basic_block_index; - ira->old_irb.current_basic_block = ira->old_irb.exec->basic_block_list.at(ira->old_bb_index); - assert(ira->old_irb.current_basic_block->in_resume_stack); - ira->old_irb.current_basic_block->in_resume_stack = false; - ira->old_irb.current_basic_block->suspended = false; + ira->zir_current_basic_block = ira->zir->basic_block_list.at(ira->old_bb_index); + assert(ira->zir_current_basic_block->in_resume_stack); + ira->zir_current_basic_block->in_resume_stack = false; + ira->zir_current_basic_block->suspended = false; ira->instruction_index = pos.instruction_index; - assert(pos.instruction_index < ira->old_irb.current_basic_block->instruction_list.length); + assert(pos.instruction_index < ira->zir_current_basic_block->instruction_list.length); if (ira->codegen->verbose_ir) { - fprintf(stderr, "%s_%" PRIu32 " #%" PRIu32 "\n", ira->old_irb.current_basic_block->name_hint, - ira->old_irb.current_basic_block->debug_id, - ira->old_irb.current_basic_block->instruction_list.at(pos.instruction_index)->base.debug_id); + fprintf(stderr, "%s_%" PRIu32 " #%" PRIu32 "\n", ira->zir_current_basic_block->name_hint, + ira->zir_current_basic_block->debug_id, + ira->zir_current_basic_block->instruction_list.at(pos.instruction_index)->base.debug_id); } ira->const_predecessor_bb = nullptr; - ira->new_irb.current_basic_block = ira->old_irb.current_basic_block->child; + ira->new_irb.current_basic_block = ira->zir_current_basic_block->child; assert(ira->new_irb.current_basic_block != nullptr); return ira->codegen->unreach_instruction; } @@ -5350,8 +5351,8 @@ static void ir_start_next_bb(IrAnalyze *ira) { bool need_repeat = true; for (;;) { - while (ira->old_bb_index < ira->old_irb.exec->basic_block_list.length) { - IrBasicBlockSrc *old_bb = ira->old_irb.exec->basic_block_list.at(ira->old_bb_index); + while (ira->old_bb_index < ira->zir->basic_block_list.length) { + IrBasicBlockSrc *old_bb = ira->zir->basic_block_list.at(ira->old_bb_index); if (old_bb->child == nullptr && old_bb->suspend_instruction_ref == nullptr) { ira->old_bb_index += 1; continue; @@ -5403,8 +5404,8 @@ static void ir_finish_bb(IrAnalyze *ira) { } } ira->instruction_index += 1; - while (ira->instruction_index < ira->old_irb.current_basic_block->instruction_list.length) { - IrInstSrc *next_instruction = ira->old_irb.current_basic_block->instruction_list.at(ira->instruction_index); + while (ira->instruction_index < ira->zir_current_basic_block->instruction_list.length) { + IrInstSrc *next_instruction = ira->zir_current_basic_block->instruction_list.at(ira->instruction_index); if (!next_instruction->is_gen) { ir_add_error(ira, &next_instruction->base, buf_sprintf("unreachable code")); break; @@ -5443,13 +5444,13 @@ static bool ir_emit_backward_branch(IrAnalyze *ira, IrInst* source_instruction) } static IrInstGen *ir_inline_bb(IrAnalyze *ira, IrInst* source_instruction, IrBasicBlockSrc *old_bb) { - if (old_bb->debug_id <= ira->old_irb.current_basic_block->debug_id) { + if (old_bb->debug_id <= ira->zir_current_basic_block->debug_id) { if (!ir_emit_backward_branch(ira, source_instruction)) return ir_unreach_error(ira); } - old_bb->child = ira->old_irb.current_basic_block->child; - ir_start_bb(ira, old_bb, ira->old_irb.current_basic_block); + old_bb->child = ira->zir_current_basic_block->child; + ir_start_bb(ira, old_bb, ira->zir_current_basic_block); return ira->codegen->unreach_instruction; } @@ -5587,7 +5588,7 @@ Error ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, if (type_is_invalid(return_ptr->type)) return ErrorSemanticAnalyzeFail; - IrExecutableSrc *ir_executable = heap::c_allocator.create(); + Stage1Zir *ir_executable = heap::c_allocator.create(); ir_executable->source_node = source_node; ir_executable->parent_exec = parent_exec; ir_executable->name = exec_name; @@ -6914,7 +6915,7 @@ static IrInstGen *ir_analyze_struct_literal_to_array(IrAnalyze *ira, IrInst* sou size_t instr_field_count = actual_type->data.structure.src_field_count; assert(array_len == instr_field_count); - bool need_comptime = ir_should_inline(ira->old_irb.exec, source_instr->scope) + bool need_comptime = ir_should_inline(ira->zir, source_instr->scope) || type_requires_comptime(ira->codegen, wanted_type) == ReqCompTimeYes; bool is_comptime = true; @@ -7004,7 +7005,7 @@ static IrInstGen *ir_analyze_struct_literal_to_struct(IrAnalyze *ira, IrInst* so size_t actual_field_count = wanted_type->data.structure.src_field_count; size_t instr_field_count = actual_type->data.structure.src_field_count; - bool need_comptime = ir_should_inline(ira->old_irb.exec, source_instr->scope) + bool need_comptime = ir_should_inline(ira->zir, source_instr->scope) || type_requires_comptime(ira->codegen, wanted_type) == ReqCompTimeYes; bool is_comptime = true; @@ -11419,7 +11420,7 @@ static IrInstGen *ir_analyze_instruction_extern(IrAnalyze *ira, IrInstSrcExtern is_thread_local, expr_type); } -static bool exec_has_err_ret_trace(CodeGen *g, IrExecutableSrc *exec) { +static bool exec_has_err_ret_trace(CodeGen *g, Stage1Zir *exec) { ZigFn *fn_entry = exec->fn_entry; return fn_entry != nullptr && fn_entry->calls_or_awaits_errorable_fn && g->have_err_ret_tracing; } @@ -11430,7 +11431,7 @@ static IrInstGen *ir_analyze_instruction_error_return_trace(IrAnalyze *ira, ZigType *ptr_to_stack_trace_type = get_pointer_to_type(ira->codegen, get_stack_trace_type(ira->codegen), false); if (instruction->optional == IrInstErrorReturnTraceNull) { ZigType *optional_type = get_optional_type(ira->codegen, ptr_to_stack_trace_type); - if (!exec_has_err_ret_trace(ira->codegen, ira->old_irb.exec)) { + if (!exec_has_err_ret_trace(ira->codegen, ira->zir)) { IrInstGen *result = ir_const(ira, &instruction->base.base, optional_type); ZigValue *out_val = result->value; assert(get_src_ptr_type(optional_type) != nullptr); @@ -13213,7 +13214,7 @@ static IrInstGen *ir_analyze_call_extra(IrAnalyze *ira, IrInst* source_instr, return ira->codegen->invalid_inst_gen; CallModifier modifier = (CallModifier)bigint_as_u32(&modifier_val->data.x_enum_tag); - if (ir_should_inline(ira->old_irb.exec, source_instr->scope)) { + if (ir_should_inline(ira->zir, source_instr->scope)) { switch (modifier) { case CallModifierBuiltin: zig_unreachable(); @@ -13302,7 +13303,7 @@ static IrInstGen *ir_analyze_async_call_extra(IrAnalyze *ira, IrInst* source_ins if (type_is_invalid(fn_ref->value->type)) return ira->codegen->invalid_inst_gen; - if (ir_should_inline(ira->old_irb.exec, source_instr->scope)) { + if (ir_should_inline(ira->zir, source_instr->scope)) { ir_add_error(ira, source_instr, buf_sprintf("TODO: comptime @asyncCall")); return ira->codegen->invalid_inst_gen; } @@ -13415,7 +13416,7 @@ static IrInstGen *ir_analyze_instruction_call(IrAnalyze *ira, IrInstSrcCall *cal return ira->codegen->invalid_inst_gen; bool is_comptime = (call_instruction->modifier == CallModifierCompileTime) || - ir_should_inline(ira->old_irb.exec, call_instruction->base.base.scope); + ir_should_inline(ira->zir, call_instruction->base.base.scope); CallModifier modifier = is_comptime ? CallModifierCompileTime : call_instruction->modifier; if (is_comptime || instr_is_comptime(fn_ref)) { @@ -13777,7 +13778,7 @@ static IrInstGen *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstSrcUnOp *in } static void ir_push_resume(IrAnalyze *ira, IrSuspendPosition pos) { - IrBasicBlockSrc *old_bb = ira->old_irb.exec->basic_block_list.at(pos.basic_block_index); + IrBasicBlockSrc *old_bb = ira->zir->basic_block_list.at(pos.basic_block_index); if (old_bb->in_resume_stack) return; ira->resume_stack.append(pos); old_bb->in_resume_stack = true; @@ -13864,7 +13865,7 @@ static IrInstGen *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstSrcCondBr static IrInstGen *ir_analyze_instruction_unreachable(IrAnalyze *ira, IrInstSrcUnreachable *unreachable_instruction) { - if (ir_should_inline(ira->old_irb.exec, unreachable_instruction->base.base.scope)) { + if (ir_should_inline(ira->zir, unreachable_instruction->base.base.scope)) { ir_add_error(ira, &unreachable_instruction->base.base, buf_sprintf("reached unreachable code")); return ir_unreach_error(ira); } @@ -16479,7 +16480,7 @@ static IrInstGen *ir_analyze_union_init(IrAnalyze *ira, IrInst* source_instructi } } - bool is_comptime = ir_should_inline(ira->old_irb.exec, source_instruction->scope) + bool is_comptime = ir_should_inline(ira->zir, source_instruction->scope) || type_requires_comptime(ira->codegen, union_type) == ReqCompTimeYes; IrInstGen *result = ir_get_deref(ira, source_instruction, result_loc, nullptr); @@ -16532,7 +16533,7 @@ static IrInstGen *ir_analyze_container_init_fields(IrAnalyze *ira, IrInst *sourc AstNode **field_assign_nodes = heap::c_allocator.allocate(actual_field_count); ZigList const_ptrs = {}; - bool is_comptime = ir_should_inline(ira->old_irb.exec, source_instr->scope) + bool is_comptime = ir_should_inline(ira->zir, source_instr->scope) || type_requires_comptime(ira->codegen, container_type) == ReqCompTimeYes; @@ -16719,7 +16720,7 @@ static IrInstGen *ir_analyze_instruction_container_init_list(IrAnalyze *ira, case ReqCompTimeInvalid: return ira->codegen->invalid_inst_gen; case ReqCompTimeNo: - is_comptime = ir_should_inline(ira->old_irb.exec, instruction->base.base.scope); + is_comptime = ir_should_inline(ira->zir, instruction->base.base.scope); break; case ReqCompTimeYes: is_comptime = true; @@ -18491,7 +18492,7 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI Buf *bare_name = buf_alloc(); Buf *full_name = get_anon_type_name(ira->codegen, - ira->old_irb.exec, "opaque", source_instr->scope, source_instr->source_node, bare_name); + ira->zir, "opaque", source_instr->scope, source_instr->source_node, bare_name); return get_opaque_type(ira->codegen, source_instr->scope, source_instr->source_node, buf_ptr(full_name), bare_name); } @@ -18538,7 +18539,7 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI assert(is_slice(slice->type)); ZigType *err_set_type = new_type_table_entry(ZigTypeIdErrorSet); Buf bare_name = BUF_INIT; - buf_init_from_buf(&err_set_type->name, get_anon_type_name(ira->codegen, ira->old_irb.exec, "error", source_instr->scope, source_instr->source_node, &bare_name)); + buf_init_from_buf(&err_set_type->name, get_anon_type_name(ira->codegen, ira->zir, "error", source_instr->scope, source_instr->source_node, &bare_name)); err_set_type->size_in_bits = ira->codegen->builtin_types.entry_global_error_set->size_in_bits; err_set_type->abi_align = ira->codegen->builtin_types.entry_global_error_set->abi_align; err_set_type->abi_size = ira->codegen->builtin_types.entry_global_error_set->abi_size; @@ -18617,7 +18618,7 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI ZigType *entry = new_type_table_entry(ZigTypeIdStruct); buf_init_from_buf(&entry->name, - get_anon_type_name(ira->codegen, ira->old_irb.exec, "struct", source_instr->scope, source_instr->source_node, &entry->name)); + get_anon_type_name(ira->codegen, ira->zir, "struct", source_instr->scope, source_instr->source_node, &entry->name)); entry->data.structure.decl_node = source_instr->source_node; entry->data.structure.fields = alloc_type_struct_fields(fields_len); entry->data.structure.fields_by_name.init(fields_len); @@ -18727,7 +18728,7 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI ZigType *entry = new_type_table_entry(ZigTypeIdEnum); buf_init_from_buf(&entry->name, - get_anon_type_name(ira->codegen, ira->old_irb.exec, "enum", source_instr->scope, source_instr->source_node, &entry->name)); + get_anon_type_name(ira->codegen, ira->zir, "enum", source_instr->scope, source_instr->source_node, &entry->name)); entry->data.enumeration.decl_node = source_instr->source_node; entry->data.enumeration.tag_int_type = tag_type; entry->data.enumeration.decls_scope = create_decls_scope( @@ -18809,7 +18810,7 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI ZigType *entry = new_type_table_entry(ZigTypeIdUnion); buf_init_from_buf(&entry->name, - get_anon_type_name(ira->codegen, ira->old_irb.exec, "union", source_instr->scope, source_instr->source_node, &entry->name)); + get_anon_type_name(ira->codegen, ira->zir, "union", source_instr->scope, source_instr->source_node, &entry->name)); entry->data.unionation.decl_node = source_instr->source_node; entry->data.unionation.fields = heap::c_allocator.allocate(fields_len); entry->data.unionation.fields_by_name.init(fields_len); @@ -22004,7 +22005,7 @@ static IrInstGen *ir_analyze_instruction_panic(IrAnalyze *ira, IrInstSrcPanic *i if (type_is_invalid(msg->value->type)) return ir_unreach_error(ira); - if (ir_should_inline(ira->old_irb.exec, instruction->base.base.scope)) { + if (ir_should_inline(ira->zir, instruction->base.base.scope)) { ir_add_error(ira, &instruction->base.base, buf_sprintf("encountered @panic at compile-time")); return ir_unreach_error(ira); } @@ -24077,7 +24078,7 @@ static IrInstGen *ir_analyze_instruction_resume(IrAnalyze *ira, IrInstSrcResume } static IrInstGen *ir_analyze_instruction_spill_begin(IrAnalyze *ira, IrInstSrcSpillBegin *instruction) { - if (ir_should_inline(ira->old_irb.exec, instruction->base.base.scope)) + if (ir_should_inline(ira->zir, instruction->base.base.scope)) return ir_const_void(ira, &instruction->base.base); IrInstGen *operand = instruction->operand->child; @@ -24103,7 +24104,7 @@ static IrInstGen *ir_analyze_instruction_spill_end(IrAnalyze *ira, IrInstSrcSpil if (type_is_invalid(operand->value->type)) return ira->codegen->invalid_inst_gen; - if (ir_should_inline(ira->old_irb.exec, instruction->base.base.scope) || + if (ir_should_inline(ira->zir, instruction->base.base.scope) || !type_has_bits(ira->codegen, operand->value->type) || instr_is_comptime(operand)) { @@ -24467,7 +24468,7 @@ static IrInstGen *ir_analyze_instruction_base(IrAnalyze *ira, IrInstSrc *instruc // This function attempts to evaluate IR code while doing type checking and other analysis. // It emits to a new IrExecutableGen which is partially evaluated IR code. -ZigType *ir_analyze(CodeGen *codegen, IrExecutableSrc *old_exec, IrExecutableGen *new_exec, +ZigType *ir_analyze(CodeGen *codegen, Stage1Zir *old_exec, IrExecutableGen *new_exec, ZigType *expected_type, AstNode *expected_type_source_node, ZigValue *result_ptr) { assert(old_exec->first_err_trace_msg == nullptr); @@ -24481,13 +24482,12 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutableSrc *old_exec, IrExecutableGen ira->explicit_return_type = expected_type; ira->explicit_return_type_source_node = expected_type_source_node; - ira->old_irb.codegen = codegen; - ira->old_irb.exec = old_exec; + ira->zir = old_exec; ira->new_irb.codegen = codegen; ira->new_irb.exec = new_exec; - IrBasicBlockSrc *old_entry_bb = ira->old_irb.exec->basic_block_list.at(0); + IrBasicBlockSrc *old_entry_bb = ira->zir->basic_block_list.at(0); IrBasicBlockGen *new_entry_bb = ir_get_new_bb(ira, old_entry_bb, nullptr); ira->new_irb.current_basic_block = new_entry_bb; ira->old_bb_index = 0; @@ -24507,8 +24507,8 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutableSrc *old_exec, IrExecutableGen get_pointer_to_type(codegen, expected_type, false)); } - while (ira->old_bb_index < ira->old_irb.exec->basic_block_list.length) { - IrInstSrc *old_instruction = ira->old_irb.current_basic_block->instruction_list.at(ira->instruction_index); + while (ira->old_bb_index < ira->zir->basic_block_list.length) { + IrInstSrc *old_instruction = ira->zir_current_basic_block->instruction_list.at(ira->instruction_index); if (old_instruction->base.ref_count == 0 && !ir_inst_src_has_side_effects(old_instruction)) { ira->instruction_index += 1; diff --git a/src/stage1/ir.hpp b/src/stage1/ir.hpp index 66f0b9a99b..a20a1782c1 100644 --- a/src/stage1/ir.hpp +++ b/src/stage1/ir.hpp @@ -20,7 +20,7 @@ Error ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, Error ir_resolve_lazy(CodeGen *codegen, AstNode *source_node, ZigValue *val); -ZigType *ir_analyze(CodeGen *g, IrExecutableSrc *old_executable, IrExecutableGen *new_executable, +ZigType *ir_analyze(CodeGen *g, Stage1Zir *old_executable, IrExecutableGen *new_executable, ZigType *expected_type, AstNode *expected_type_source_node, ZigValue *return_ptr); bool ir_inst_gen_has_side_effects(IrInstGen *inst); diff --git a/src/stage1/ir_print.cpp b/src/stage1/ir_print.cpp index 22b6c1ed5f..8820db81d4 100644 --- a/src/stage1/ir_print.cpp +++ b/src/stage1/ir_print.cpp @@ -3395,7 +3395,7 @@ void ir_print_basic_block_gen(CodeGen *codegen, FILE *f, IrBasicBlockGen *bb, in ir_print.printed.deinit(); } -void ir_print_src(CodeGen *codegen, FILE *f, IrExecutableSrc *executable, int indent_size) { +void ir_print_src(CodeGen *codegen, FILE *f, Stage1Zir *executable, int indent_size) { IrPrintSrc ir_print = {}; IrPrintSrc *irp = &ir_print; irp->codegen = codegen; diff --git a/src/stage1/ir_print.hpp b/src/stage1/ir_print.hpp index dde5aaea67..a20ef8808c 100644 --- a/src/stage1/ir_print.hpp +++ b/src/stage1/ir_print.hpp @@ -12,7 +12,7 @@ #include -void ir_print_src(CodeGen *codegen, FILE *f, IrExecutableSrc *executable, int indent_size); +void ir_print_src(CodeGen *codegen, FILE *f, Stage1Zir *executable, int indent_size); void ir_print_gen(CodeGen *codegen, FILE *f, IrExecutableGen *executable, int indent_size); void ir_print_inst_src(CodeGen *codegen, FILE *f, IrInstSrc *inst, int indent_size); void ir_print_inst_gen(CodeGen *codegen, FILE *f, IrInstGen *inst, int indent_size); From b11ac9c5bfb4048eb4aa561f8b3b058a76787f7e Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 27 May 2021 18:40:47 -0700 Subject: [PATCH 04/14] stage1: move some mutable state from Stage1Zir to IrAnalyze This is progress towards making Stage1Zir immutable, so that we can avoid generating it for every comptime function call. Also rename IrExecutableGen to Stage1Air. --- src/stage1/all_types.hpp | 19 ++-- src/stage1/analyze.cpp | 18 ++-- src/stage1/astgen.cpp | 12 +-- src/stage1/astgen.hpp | 2 +- src/stage1/codegen.cpp | 182 +++++++++++++++++++-------------------- src/stage1/ir.cpp | 91 ++++++++++---------- src/stage1/ir.hpp | 7 +- src/stage1/ir_print.cpp | 2 +- src/stage1/ir_print.hpp | 2 +- 9 files changed, 157 insertions(+), 178 deletions(-) diff --git a/src/stage1/all_types.hpp b/src/stage1/all_types.hpp index f27168ca2f..56763b4d7f 100644 --- a/src/stage1/all_types.hpp +++ b/src/stage1/all_types.hpp @@ -51,7 +51,7 @@ struct ResultLocPeerParent; struct ResultLocBitCast; struct ResultLocCast; struct ResultLocReturn; -struct IrExecutableGen; +struct Stage1Air; enum FileExt { FileExtUnknown, @@ -116,19 +116,14 @@ struct Stage1Zir { ZigFn *name_fn; size_t mem_slot_count; size_t next_debug_id; - size_t *backward_branch_count; - size_t *backward_branch_quota; ZigFn *fn_entry; Buf *c_import_buf; AstNode *source_node; - IrExecutableGen *parent_exec; - IrAnalyze *analysis; Scope *begin_scope; ErrorMsg *first_err_trace_msg; ZigList tld_list; bool is_inline; - bool is_generic_instantiation; bool need_err_code_spill; // This is a function for use in the debugger to print @@ -136,25 +131,22 @@ struct Stage1Zir { void src(); }; -struct IrExecutableGen { +struct Stage1Air { ZigList basic_block_list; Buf *name; ZigFn *name_fn; size_t mem_slot_count; size_t next_debug_id; - size_t *backward_branch_count; - size_t *backward_branch_quota; ZigFn *fn_entry; Buf *c_import_buf; AstNode *source_node; - IrExecutableGen *parent_exec; + Stage1Air *parent_exec; Stage1Zir *source_exec; Scope *begin_scope; ErrorMsg *first_err_trace_msg; ZigList tld_list; bool is_inline; - bool is_generic_instantiation; bool need_err_code_spill; // This is a function for use in the debugger to print @@ -1652,9 +1644,8 @@ struct ZigFn { // zig source code, not according to zig ir ZigType *src_implicit_return_type; Stage1Zir *ir_executable; - IrExecutableGen analyzed_executable; - size_t prealloc_bbc; - size_t prealloc_backward_branch_quota; + Stage1Air analyzed_executable; + size_t branch_quota; AstNode **param_source_nodes; Buf **param_names; IrInstGen *err_code_spill; diff --git a/src/stage1/analyze.cpp b/src/stage1/analyze.cpp index fa53fae075..dc17cfb493 100644 --- a/src/stage1/analyze.cpp +++ b/src/stage1/analyze.cpp @@ -3655,10 +3655,6 @@ static ZigFn *create_fn_raw(CodeGen *g, bool is_noinline) { ZigFn *fn_entry = heap::c_allocator.create(); fn_entry->ir_executable = heap::c_allocator.create(); - fn_entry->prealloc_backward_branch_quota = default_backward_branch_quota; - - fn_entry->analyzed_executable.backward_branch_count = &fn_entry->prealloc_bbc; - fn_entry->analyzed_executable.backward_branch_quota = &fn_entry->prealloc_backward_branch_quota; fn_entry->analyzed_executable.fn_entry = fn_entry; fn_entry->ir_executable->fn_entry = fn_entry; fn_entry->is_noinline = is_noinline; @@ -5134,8 +5130,11 @@ static void analyze_fn_ir(CodeGen *g, ZigFn *fn, AstNode *return_type_node) { if (fn->analyzed_executable.source_node == nullptr) { fn->analyzed_executable.source_node = fn->body_node; } - ZigType *block_return_type = ir_analyze(g, fn->ir_executable, - &fn->analyzed_executable, fn_type_id->return_type, return_type_node, nullptr); + size_t backward_branch_count = 0; + size_t backward_branch_quota = max(fn->branch_quota, default_backward_branch_quota); + ZigType *block_return_type = ir_analyze(g, fn->ir_executable, &fn->analyzed_executable, + &backward_branch_count, &backward_branch_quota, + fn_type_id->return_type, return_type_node, nullptr); fn->src_implicit_return_type = block_return_type; if (type_is_invalid(block_return_type) || fn->analyzed_executable.first_err_trace_msg != nullptr) { @@ -9866,13 +9865,10 @@ void Stage1Zir::src() { if (this->source_node != nullptr) { this->source_node->src(); } - if (this->parent_exec != nullptr) { - this->parent_exec->src(); - } } -void IrExecutableGen::src() { - IrExecutableGen *it; +void Stage1Air::src() { + Stage1Air *it; for (it = this; it != nullptr && it->source_node != nullptr; it = it->parent_exec) { it->source_node->src(); } diff --git a/src/stage1/astgen.cpp b/src/stage1/astgen.cpp index 3dd4e39dcb..11c82701f5 100644 --- a/src/stage1/astgen.cpp +++ b/src/stage1/astgen.cpp @@ -41,19 +41,9 @@ static void ir_assert_impl(bool ok, IrInst *source_instruction, char const *file src_assert_impl(ok, source_instruction->source_node, file, line); } -static void ir_add_call_stack_errors(CodeGen *codegen, Stage1Zir *exec, ErrorMsg *err_msg, int limit) { - if (!exec || !exec->source_node || limit < 0) return; - add_error_note(codegen, err_msg, exec->source_node, buf_sprintf("called from here")); - - ir_add_call_stack_errors_gen(codegen, exec->parent_exec, err_msg, limit - 1); -} - static ErrorMsg *exec_add_error_node(CodeGen *codegen, Stage1Zir *exec, AstNode *source_node, Buf *msg) { ErrorMsg *err_msg = add_node_error(codegen, source_node, msg); invalidate_exec(exec, err_msg); - if (exec->parent_exec) { - ir_add_call_stack_errors(codegen, exec, err_msg, 10); - } return err_msg; } @@ -8118,7 +8108,7 @@ AstNode *ast_field_to_symbol_node(AstNode *err_set_field_node) { } } -void ir_add_call_stack_errors_gen(CodeGen *codegen, IrExecutableGen *exec, ErrorMsg *err_msg, int limit) { +void ir_add_call_stack_errors_gen(CodeGen *codegen, Stage1Air *exec, ErrorMsg *err_msg, int limit) { if (!exec || !exec->source_node || limit < 0) return; add_error_note(codegen, err_msg, exec->source_node, buf_sprintf("called from here")); diff --git a/src/stage1/astgen.hpp b/src/stage1/astgen.hpp index 9b78b2496b..2113637df2 100644 --- a/src/stage1/astgen.hpp +++ b/src/stage1/astgen.hpp @@ -24,7 +24,7 @@ ResultLoc *no_result_loc(void); void invalidate_exec(Stage1Zir *exec, ErrorMsg *msg); AstNode *ast_field_to_symbol_node(AstNode *err_set_field_node); -void ir_add_call_stack_errors_gen(CodeGen *codegen, IrExecutableGen *exec, ErrorMsg *err_msg, +void ir_add_call_stack_errors_gen(CodeGen *codegen, Stage1Air *exec, ErrorMsg *err_msg, int limit); void destroy_instruction_src(IrInstSrc *inst); diff --git a/src/stage1/codegen.cpp b/src/stage1/codegen.cpp index 1dd3aa8d45..043281f2a7 100644 --- a/src/stage1/codegen.cpp +++ b/src/stage1/codegen.cpp @@ -2443,7 +2443,7 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) { return fn_val; } -static LLVMValueRef ir_render_save_err_ret_addr(CodeGen *g, IrExecutableGen *executable, +static LLVMValueRef ir_render_save_err_ret_addr(CodeGen *g, Stage1Air *executable, IrInstGenSaveErrRetAddr *save_err_ret_addr_instruction) { assert(g->have_err_ret_tracing); @@ -2636,7 +2636,7 @@ static void gen_async_return(CodeGen *g, IrInstGenReturn *instruction) { LLVMBuildRetVoid(g->builder); } -static LLVMValueRef ir_render_return(CodeGen *g, IrExecutableGen *executable, IrInstGenReturn *instruction) { +static LLVMValueRef ir_render_return(CodeGen *g, Stage1Air *executable, IrInstGenReturn *instruction) { if (fn_is_async(g->cur_fn)) { gen_async_return(g, instruction); return nullptr; @@ -3061,7 +3061,7 @@ static void gen_shift_rhs_check(CodeGen *g, ZigType *lhs_type, ZigType *rhs_type } } -static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutableGen *executable, +static LLVMValueRef ir_render_bin_op(CodeGen *g, Stage1Air *executable, IrInstGenBinOp *bin_op_instruction) { IrBinOp op_id = bin_op_instruction->op_id; @@ -3283,7 +3283,7 @@ static void add_error_range_check(CodeGen *g, ZigType *err_set_type, ZigType *in } } -static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutableGen *executable, +static LLVMValueRef ir_render_cast(CodeGen *g, Stage1Air *executable, IrInstGenCast *cast_instruction) { Error err; @@ -3367,7 +3367,7 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutableGen *executable, zig_unreachable(); } -static LLVMValueRef ir_render_ptr_of_array_to_slice(CodeGen *g, IrExecutableGen *executable, +static LLVMValueRef ir_render_ptr_of_array_to_slice(CodeGen *g, Stage1Air *executable, IrInstGenPtrOfArrayToSlice *instruction) { ZigType *actual_type = instruction->operand->value->type; @@ -3404,7 +3404,7 @@ static LLVMValueRef ir_render_ptr_of_array_to_slice(CodeGen *g, IrExecutableGen return result_loc; } -static LLVMValueRef ir_render_ptr_cast(CodeGen *g, IrExecutableGen *executable, +static LLVMValueRef ir_render_ptr_cast(CodeGen *g, Stage1Air *executable, IrInstGenPtrCast *instruction) { ZigType *wanted_type = instruction->base.value->type; @@ -3430,7 +3430,7 @@ static LLVMValueRef ir_render_ptr_cast(CodeGen *g, IrExecutableGen *executable, return result_ptr; } -static LLVMValueRef ir_render_bit_cast(CodeGen *g, IrExecutableGen *executable, +static LLVMValueRef ir_render_bit_cast(CodeGen *g, Stage1Air *executable, IrInstGenBitCast *instruction) { ZigType *wanted_type = instruction->base.value->type; @@ -3458,7 +3458,7 @@ static LLVMValueRef ir_render_bit_cast(CodeGen *g, IrExecutableGen *executable, } } -static LLVMValueRef ir_render_widen_or_shorten(CodeGen *g, IrExecutableGen *executable, +static LLVMValueRef ir_render_widen_or_shorten(CodeGen *g, Stage1Air *executable, IrInstGenWidenOrShorten *instruction) { ZigType *actual_type = instruction->target->value->type; @@ -3475,7 +3475,7 @@ static LLVMValueRef ir_render_widen_or_shorten(CodeGen *g, IrExecutableGen *exec instruction->base.value->type, target_val); } -static LLVMValueRef ir_render_int_to_ptr(CodeGen *g, IrExecutableGen *executable, IrInstGenIntToPtr *instruction) { +static LLVMValueRef ir_render_int_to_ptr(CodeGen *g, Stage1Air *executable, IrInstGenIntToPtr *instruction) { ZigType *wanted_type = instruction->base.value->type; LLVMValueRef target_val = ir_llvm_value(g, instruction->target); const uint32_t align_bytes = get_ptr_align(g, wanted_type); @@ -3513,13 +3513,13 @@ static LLVMValueRef ir_render_int_to_ptr(CodeGen *g, IrExecutableGen *executable return LLVMBuildIntToPtr(g->builder, target_val, get_llvm_type(g, wanted_type), ""); } -static LLVMValueRef ir_render_ptr_to_int(CodeGen *g, IrExecutableGen *executable, IrInstGenPtrToInt *instruction) { +static LLVMValueRef ir_render_ptr_to_int(CodeGen *g, Stage1Air *executable, IrInstGenPtrToInt *instruction) { ZigType *wanted_type = instruction->base.value->type; LLVMValueRef target_val = ir_llvm_value(g, instruction->target); return LLVMBuildPtrToInt(g->builder, target_val, get_llvm_type(g, wanted_type), ""); } -static LLVMValueRef ir_render_int_to_enum(CodeGen *g, IrExecutableGen *executable, IrInstGenIntToEnum *instruction) { +static LLVMValueRef ir_render_int_to_enum(CodeGen *g, Stage1Air *executable, IrInstGenIntToEnum *instruction) { ZigType *wanted_type = instruction->base.value->type; assert(wanted_type->id == ZigTypeIdEnum); ZigType *tag_int_type = wanted_type->data.enumeration.tag_int_type; @@ -3559,7 +3559,7 @@ static LLVMValueRef ir_render_int_to_enum(CodeGen *g, IrExecutableGen *executabl return tag_int_value; } -static LLVMValueRef ir_render_int_to_err(CodeGen *g, IrExecutableGen *executable, IrInstGenIntToErr *instruction) { +static LLVMValueRef ir_render_int_to_err(CodeGen *g, Stage1Air *executable, IrInstGenIntToErr *instruction) { ZigType *wanted_type = instruction->base.value->type; assert(wanted_type->id == ZigTypeIdErrorSet); @@ -3576,7 +3576,7 @@ static LLVMValueRef ir_render_int_to_err(CodeGen *g, IrExecutableGen *executable return gen_widen_or_shorten(g, false, actual_type, g->err_tag_type, target_val); } -static LLVMValueRef ir_render_err_to_int(CodeGen *g, IrExecutableGen *executable, IrInstGenErrToInt *instruction) { +static LLVMValueRef ir_render_err_to_int(CodeGen *g, Stage1Air *executable, IrInstGenErrToInt *instruction) { ZigType *wanted_type = instruction->base.value->type; assert(wanted_type->id == ZigTypeIdInt); assert(!wanted_type->data.integral.is_signed); @@ -3602,7 +3602,7 @@ static LLVMValueRef ir_render_err_to_int(CodeGen *g, IrExecutableGen *executable } } -static LLVMValueRef ir_render_unreachable(CodeGen *g, IrExecutableGen *executable, +static LLVMValueRef ir_render_unreachable(CodeGen *g, Stage1Air *executable, IrInstGenUnreachable *unreachable_instruction) { if (ir_want_runtime_safety(g, &unreachable_instruction->base)) { @@ -3613,7 +3613,7 @@ static LLVMValueRef ir_render_unreachable(CodeGen *g, IrExecutableGen *executabl return nullptr; } -static LLVMValueRef ir_render_cond_br(CodeGen *g, IrExecutableGen *executable, +static LLVMValueRef ir_render_cond_br(CodeGen *g, Stage1Air *executable, IrInstGenCondBr *cond_br_instruction) { LLVMBuildCondBr(g->builder, @@ -3623,12 +3623,12 @@ static LLVMValueRef ir_render_cond_br(CodeGen *g, IrExecutableGen *executable, return nullptr; } -static LLVMValueRef ir_render_br(CodeGen *g, IrExecutableGen *executable, IrInstGenBr *br_instruction) { +static LLVMValueRef ir_render_br(CodeGen *g, Stage1Air *executable, IrInstGenBr *br_instruction) { LLVMBuildBr(g->builder, br_instruction->dest_block->llvm_block); return nullptr; } -static LLVMValueRef ir_render_binary_not(CodeGen *g, IrExecutableGen *executable, +static LLVMValueRef ir_render_binary_not(CodeGen *g, Stage1Air *executable, IrInstGenBinaryNot *inst) { LLVMValueRef operand = ir_llvm_value(g, inst->operand); @@ -3660,13 +3660,13 @@ static LLVMValueRef ir_gen_negation(CodeGen *g, IrInstGen *inst, IrInstGen *oper } } -static LLVMValueRef ir_render_negation(CodeGen *g, IrExecutableGen *executable, +static LLVMValueRef ir_render_negation(CodeGen *g, Stage1Air *executable, IrInstGenNegation *inst) { return ir_gen_negation(g, &inst->base, inst->operand, inst->wrapping); } -static LLVMValueRef ir_render_bool_not(CodeGen *g, IrExecutableGen *executable, IrInstGenBoolNot *instruction) { +static LLVMValueRef ir_render_bool_not(CodeGen *g, Stage1Air *executable, IrInstGenBoolNot *instruction) { LLVMValueRef value = ir_llvm_value(g, instruction->value); LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(value)); return LLVMBuildICmp(g->builder, LLVMIntEQ, value, zero, ""); @@ -3680,14 +3680,14 @@ static void render_decl_var(CodeGen *g, ZigVar *var) { gen_var_debug_decl(g, var); } -static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutableGen *executable, IrInstGenDeclVar *instruction) { +static LLVMValueRef ir_render_decl_var(CodeGen *g, Stage1Air *executable, IrInstGenDeclVar *instruction) { instruction->var->ptr_instruction = instruction->var_ptr; instruction->var->did_the_decl_codegen = true; render_decl_var(g, instruction->var); return nullptr; } -static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutableGen *executable, +static LLVMValueRef ir_render_load_ptr(CodeGen *g, Stage1Air *executable, IrInstGenLoadPtr *instruction) { ZigType *child_type = instruction->base.value->type; @@ -3889,7 +3889,7 @@ static void gen_undef_init(CodeGen *g, ZigType *ptr_type, ZigType *value_type, L gen_assign_raw(g, ptr, ptr_type, zero); } -static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutableGen *executable, IrInstGenStorePtr *instruction) { +static LLVMValueRef ir_render_store_ptr(CodeGen *g, Stage1Air *executable, IrInstGenStorePtr *instruction) { Error err; ZigType *ptr_type = instruction->ptr->value->type; @@ -3921,7 +3921,7 @@ static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutableGen *executable, return nullptr; } -static LLVMValueRef ir_render_vector_store_elem(CodeGen *g, IrExecutableGen *executable, +static LLVMValueRef ir_render_vector_store_elem(CodeGen *g, Stage1Air *executable, IrInstGenVectorStoreElem *instruction) { LLVMValueRef vector_ptr = ir_llvm_value(g, instruction->vector_ptr); @@ -3934,7 +3934,7 @@ static LLVMValueRef ir_render_vector_store_elem(CodeGen *g, IrExecutableGen *exe return nullptr; } -static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutableGen *executable, IrInstGenVarPtr *instruction) { +static LLVMValueRef ir_render_var_ptr(CodeGen *g, Stage1Air *executable, IrInstGenVarPtr *instruction) { Error err; ZigType *ptr_type = instruction->base.value->type; @@ -3961,7 +3961,7 @@ static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutableGen *executable, I get_llvm_type(g, ptr_type), ""); } -static LLVMValueRef ir_render_return_ptr(CodeGen *g, IrExecutableGen *executable, +static LLVMValueRef ir_render_return_ptr(CodeGen *g, Stage1Air *executable, IrInstGenReturnPtr *instruction) { if (!type_has_bits(g, instruction->base.value->type)) @@ -3970,7 +3970,7 @@ static LLVMValueRef ir_render_return_ptr(CodeGen *g, IrExecutableGen *executable return g->cur_ret_ptr; } -static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutableGen *executable, IrInstGenElemPtr *instruction) { +static LLVMValueRef ir_render_elem_ptr(CodeGen *g, Stage1Air *executable, IrInstGenElemPtr *instruction) { LLVMValueRef array_ptr_ptr = ir_llvm_value(g, instruction->array_ptr); ZigType *array_ptr_type = instruction->array_ptr->value->type; assert(array_ptr_type->id == ZigTypeIdPointer); @@ -4222,7 +4222,7 @@ static void gen_init_stack_trace(CodeGen *g, LLVMValueRef trace_field_ptr, LLVMV LLVMBuildStore(g->builder, LLVMConstInt(usize_type_ref, stack_trace_ptr_count, false), addrs_len_ptr); } -static LLVMValueRef ir_render_call(CodeGen *g, IrExecutableGen *executable, IrInstGenCall *instruction) { +static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, IrInstGenCall *instruction) { Error err; LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; @@ -4642,7 +4642,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutableGen *executable, IrIn } } -static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutableGen *executable, +static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, Stage1Air *executable, IrInstGenStructFieldPtr *instruction) { Error err; @@ -4693,7 +4693,7 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutableGen *exec return field_ptr_val; } -static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutableGen *executable, +static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, Stage1Air *executable, IrInstGenUnionFieldPtr *instruction) { if (instruction->base.value->special != ConstValSpecialRuntime) @@ -4793,7 +4793,7 @@ static size_t find_asm_index(CodeGen *g, AstNode *node, AsmToken *tok, Buf *src_ return SIZE_MAX; } -static LLVMValueRef ir_render_asm_gen(CodeGen *g, IrExecutableGen *executable, IrInstGenAsm *instruction) { +static LLVMValueRef ir_render_asm_gen(CodeGen *g, Stage1Air *executable, IrInstGenAsm *instruction) { AstNode *asm_node = instruction->base.base.source_node; assert(asm_node->type == NodeTypeAsmExpr); AstNodeAsmExpr *asm_expr = &asm_node->data.asm_expr; @@ -4970,13 +4970,13 @@ static LLVMValueRef gen_non_null_bit(CodeGen *g, ZigType *maybe_type, LLVMValueR return gen_load_untyped(g, maybe_field_ptr, 0, false, ""); } -static LLVMValueRef ir_render_test_non_null(CodeGen *g, IrExecutableGen *executable, +static LLVMValueRef ir_render_test_non_null(CodeGen *g, Stage1Air *executable, IrInstGenTestNonNull *instruction) { return gen_non_null_bit(g, instruction->value->value->type, ir_llvm_value(g, instruction->value)); } -static LLVMValueRef ir_render_optional_unwrap_ptr(CodeGen *g, IrExecutableGen *executable, +static LLVMValueRef ir_render_optional_unwrap_ptr(CodeGen *g, Stage1Air *executable, IrInstGenOptionalUnwrapPtr *instruction) { if (instruction->base.value->special != ConstValSpecialRuntime) @@ -5083,7 +5083,7 @@ static LLVMValueRef get_int_builtin_fn(CodeGen *g, ZigType *expr_type, BuiltinFn return fn_val; } -static LLVMValueRef ir_render_clz(CodeGen *g, IrExecutableGen *executable, IrInstGenClz *instruction) { +static LLVMValueRef ir_render_clz(CodeGen *g, Stage1Air *executable, IrInstGenClz *instruction) { ZigType *int_type = instruction->op->value->type; LLVMValueRef fn_val = get_int_builtin_fn(g, int_type, BuiltinFnIdClz); LLVMValueRef operand = ir_llvm_value(g, instruction->op); @@ -5095,7 +5095,7 @@ static LLVMValueRef ir_render_clz(CodeGen *g, IrExecutableGen *executable, IrIns return gen_widen_or_shorten(g, false, int_type, instruction->base.value->type, wrong_size_int); } -static LLVMValueRef ir_render_ctz(CodeGen *g, IrExecutableGen *executable, IrInstGenCtz *instruction) { +static LLVMValueRef ir_render_ctz(CodeGen *g, Stage1Air *executable, IrInstGenCtz *instruction) { ZigType *int_type = instruction->op->value->type; LLVMValueRef fn_val = get_int_builtin_fn(g, int_type, BuiltinFnIdCtz); LLVMValueRef operand = ir_llvm_value(g, instruction->op); @@ -5107,7 +5107,7 @@ static LLVMValueRef ir_render_ctz(CodeGen *g, IrExecutableGen *executable, IrIns return gen_widen_or_shorten(g, false, int_type, instruction->base.value->type, wrong_size_int); } -static LLVMValueRef ir_render_shuffle_vector(CodeGen *g, IrExecutableGen *executable, IrInstGenShuffleVector *instruction) { +static LLVMValueRef ir_render_shuffle_vector(CodeGen *g, Stage1Air *executable, IrInstGenShuffleVector *instruction) { uint64_t len_a = instruction->a->value->type->data.vector.len; uint64_t len_mask = instruction->mask->value->type->data.vector.len; @@ -5137,7 +5137,7 @@ static LLVMValueRef ir_render_shuffle_vector(CodeGen *g, IrExecutableGen *execut llvm_mask_value, ""); } -static LLVMValueRef ir_render_splat(CodeGen *g, IrExecutableGen *executable, IrInstGenSplat *instruction) { +static LLVMValueRef ir_render_splat(CodeGen *g, Stage1Air *executable, IrInstGenSplat *instruction) { ZigType *result_type = instruction->base.value->type; ir_assert(result_type->id == ZigTypeIdVector, &instruction->base); uint32_t len = result_type->data.vector.len; @@ -5149,7 +5149,7 @@ static LLVMValueRef ir_render_splat(CodeGen *g, IrExecutableGen *executable, IrI return LLVMBuildShuffleVector(g->builder, op_vector, undef_vector, LLVMConstNull(mask_llvm_type), ""); } -static LLVMValueRef ir_render_pop_count(CodeGen *g, IrExecutableGen *executable, IrInstGenPopCount *instruction) { +static LLVMValueRef ir_render_pop_count(CodeGen *g, Stage1Air *executable, IrInstGenPopCount *instruction) { ZigType *int_type = instruction->op->value->type; LLVMValueRef fn_val = get_int_builtin_fn(g, int_type, BuiltinFnIdPopCount); LLVMValueRef operand = ir_llvm_value(g, instruction->op); @@ -5157,7 +5157,7 @@ static LLVMValueRef ir_render_pop_count(CodeGen *g, IrExecutableGen *executable, return gen_widen_or_shorten(g, false, int_type, instruction->base.value->type, wrong_size_int); } -static LLVMValueRef ir_render_switch_br(CodeGen *g, IrExecutableGen *executable, IrInstGenSwitchBr *instruction) { +static LLVMValueRef ir_render_switch_br(CodeGen *g, Stage1Air *executable, IrInstGenSwitchBr *instruction) { ZigType *target_type = instruction->target_value->value->type; LLVMBasicBlockRef else_block = instruction->else_block->llvm_block; @@ -5185,7 +5185,7 @@ static LLVMValueRef ir_render_switch_br(CodeGen *g, IrExecutableGen *executable, return nullptr; } -static LLVMValueRef ir_render_phi(CodeGen *g, IrExecutableGen *executable, IrInstGenPhi *instruction) { +static LLVMValueRef ir_render_phi(CodeGen *g, Stage1Air *executable, IrInstGenPhi *instruction) { if (!type_has_bits(g, instruction->base.value->type)) return nullptr; @@ -5209,7 +5209,7 @@ static LLVMValueRef ir_render_phi(CodeGen *g, IrExecutableGen *executable, IrIns return phi; } -static LLVMValueRef ir_render_ref(CodeGen *g, IrExecutableGen *executable, IrInstGenRef *instruction) { +static LLVMValueRef ir_render_ref(CodeGen *g, Stage1Air *executable, IrInstGenRef *instruction) { if (!type_has_bits(g, instruction->base.value->type)) { return nullptr; } @@ -5229,7 +5229,7 @@ static LLVMValueRef ir_render_ref(CodeGen *g, IrExecutableGen *executable, IrIns } } -static LLVMValueRef ir_render_err_name(CodeGen *g, IrExecutableGen *executable, IrInstGenErrName *instruction) { +static LLVMValueRef ir_render_err_name(CodeGen *g, Stage1Air *executable, IrInstGenErrName *instruction) { assert(g->generate_error_name_table); assert(g->errors_by_index.length > 0); @@ -5356,7 +5356,7 @@ static LLVMValueRef get_enum_tag_name_function(CodeGen *g, ZigType *enum_type) { return fn_val; } -static LLVMValueRef ir_render_enum_tag_name(CodeGen *g, IrExecutableGen *executable, +static LLVMValueRef ir_render_enum_tag_name(CodeGen *g, Stage1Air *executable, IrInstGenTagName *instruction) { ZigType *enum_type = instruction->target->value->type; @@ -5369,7 +5369,7 @@ static LLVMValueRef ir_render_enum_tag_name(CodeGen *g, IrExecutableGen *executa get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, ""); } -static LLVMValueRef ir_render_field_parent_ptr(CodeGen *g, IrExecutableGen *executable, +static LLVMValueRef ir_render_field_parent_ptr(CodeGen *g, Stage1Air *executable, IrInstGenFieldParentPtr *instruction) { ZigType *container_ptr_type = instruction->base.value->type; @@ -5396,7 +5396,7 @@ static LLVMValueRef ir_render_field_parent_ptr(CodeGen *g, IrExecutableGen *exec } } -static LLVMValueRef ir_render_align_cast(CodeGen *g, IrExecutableGen *executable, IrInstGenAlignCast *instruction) { +static LLVMValueRef ir_render_align_cast(CodeGen *g, Stage1Air *executable, IrInstGenAlignCast *instruction) { LLVMValueRef target_val = ir_llvm_value(g, instruction->target); assert(target_val); @@ -5459,7 +5459,7 @@ static LLVMValueRef ir_render_align_cast(CodeGen *g, IrExecutableGen *executable return target_val; } -static LLVMValueRef ir_render_error_return_trace(CodeGen *g, IrExecutableGen *executable, +static LLVMValueRef ir_render_error_return_trace(CodeGen *g, Stage1Air *executable, IrInstGenErrorReturnTrace *instruction) { bool is_llvm_alloca; @@ -5530,7 +5530,7 @@ static LLVMTypeRef get_atomic_abi_type(CodeGen *g, IrInstGen *instruction) { } } -static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutableGen *executable, IrInstGenCmpxchg *instruction) { +static LLVMValueRef ir_render_cmpxchg(CodeGen *g, Stage1Air *executable, IrInstGenCmpxchg *instruction) { LLVMValueRef ptr_val = ir_llvm_value(g, instruction->ptr); LLVMValueRef cmp_val = ir_llvm_value(g, instruction->cmp_value); LLVMValueRef new_val = ir_llvm_value(g, instruction->new_value); @@ -5592,7 +5592,7 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutableGen *executable, I return result_loc; } -static LLVMValueRef ir_render_reduce(CodeGen *g, IrExecutableGen *executable, IrInstGenReduce *instruction) { +static LLVMValueRef ir_render_reduce(CodeGen *g, Stage1Air *executable, IrInstGenReduce *instruction) { LLVMValueRef value = ir_llvm_value(g, instruction->value); ZigType *value_type = instruction->value->value->type; @@ -5656,13 +5656,13 @@ static LLVMValueRef ir_render_reduce(CodeGen *g, IrExecutableGen *executable, Ir return result_val; } -static LLVMValueRef ir_render_fence(CodeGen *g, IrExecutableGen *executable, IrInstGenFence *instruction) { +static LLVMValueRef ir_render_fence(CodeGen *g, Stage1Air *executable, IrInstGenFence *instruction) { LLVMAtomicOrdering atomic_order = to_LLVMAtomicOrdering(instruction->order); LLVMBuildFence(g->builder, atomic_order, false, ""); return nullptr; } -static LLVMValueRef ir_render_truncate(CodeGen *g, IrExecutableGen *executable, IrInstGenTruncate *instruction) { +static LLVMValueRef ir_render_truncate(CodeGen *g, Stage1Air *executable, IrInstGenTruncate *instruction) { LLVMValueRef target_val = ir_llvm_value(g, instruction->target); ZigType *dest_type = instruction->base.value->type; ZigType *src_type = instruction->target->value->type; @@ -5677,7 +5677,7 @@ static LLVMValueRef ir_render_truncate(CodeGen *g, IrExecutableGen *executable, } } -static LLVMValueRef ir_render_memset(CodeGen *g, IrExecutableGen *executable, IrInstGenMemset *instruction) { +static LLVMValueRef ir_render_memset(CodeGen *g, Stage1Air *executable, IrInstGenMemset *instruction) { LLVMValueRef dest_ptr = ir_llvm_value(g, instruction->dest_ptr); LLVMValueRef len_val = ir_llvm_value(g, instruction->count); @@ -5707,7 +5707,7 @@ static LLVMValueRef ir_render_memset(CodeGen *g, IrExecutableGen *executable, Ir return nullptr; } -static LLVMValueRef ir_render_memcpy(CodeGen *g, IrExecutableGen *executable, IrInstGenMemcpy *instruction) { +static LLVMValueRef ir_render_memcpy(CodeGen *g, Stage1Air *executable, IrInstGenMemcpy *instruction) { LLVMValueRef dest_ptr = ir_llvm_value(g, instruction->dest_ptr); LLVMValueRef src_ptr = ir_llvm_value(g, instruction->src_ptr); LLVMValueRef len_val = ir_llvm_value(g, instruction->count); @@ -5729,14 +5729,14 @@ static LLVMValueRef ir_render_memcpy(CodeGen *g, IrExecutableGen *executable, Ir return nullptr; } -static LLVMValueRef ir_render_wasm_memory_size(CodeGen *g, IrExecutableGen *executable, IrInstGenWasmMemorySize *instruction) { +static LLVMValueRef ir_render_wasm_memory_size(CodeGen *g, Stage1Air *executable, IrInstGenWasmMemorySize *instruction) { // TODO adjust for wasm64 LLVMValueRef param = ir_llvm_value(g, instruction->index); LLVMValueRef val = LLVMBuildCall(g->builder, gen_wasm_memory_size(g), ¶m, 1, ""); return val; } -static LLVMValueRef ir_render_wasm_memory_grow(CodeGen *g, IrExecutableGen *executable, IrInstGenWasmMemoryGrow *instruction) { +static LLVMValueRef ir_render_wasm_memory_grow(CodeGen *g, Stage1Air *executable, IrInstGenWasmMemoryGrow *instruction) { // TODO adjust for wasm64 LLVMValueRef params[] = { ir_llvm_value(g, instruction->index), @@ -5746,7 +5746,7 @@ static LLVMValueRef ir_render_wasm_memory_grow(CodeGen *g, IrExecutableGen *exec return val; } -static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrInstGenSlice *instruction) { +static LLVMValueRef ir_render_slice(CodeGen *g, Stage1Air *executable, IrInstGenSlice *instruction) { Error err; LLVMValueRef array_ptr_ptr = ir_llvm_value(g, instruction->ptr); @@ -5983,12 +5983,12 @@ static LLVMValueRef get_trap_fn_val(CodeGen *g) { } -static LLVMValueRef ir_render_breakpoint(CodeGen *g, IrExecutableGen *executable, IrInstGenBreakpoint *instruction) { +static LLVMValueRef ir_render_breakpoint(CodeGen *g, Stage1Air *executable, IrInstGenBreakpoint *instruction) { LLVMBuildCall(g->builder, get_trap_fn_val(g), nullptr, 0, ""); return nullptr; } -static LLVMValueRef ir_render_return_address(CodeGen *g, IrExecutableGen *executable, +static LLVMValueRef ir_render_return_address(CodeGen *g, Stage1Air *executable, IrInstGenReturnAddress *instruction) { if (target_is_wasm(g->zig_target) && g->zig_target->os != OsEmscripten) { @@ -6016,7 +6016,7 @@ static LLVMValueRef get_frame_address_fn_val(CodeGen *g) { return g->frame_address_fn_val; } -static LLVMValueRef ir_render_frame_address(CodeGen *g, IrExecutableGen *executable, +static LLVMValueRef ir_render_frame_address(CodeGen *g, Stage1Air *executable, IrInstGenFrameAddress *instruction) { LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_i32->llvm_type); @@ -6024,7 +6024,7 @@ static LLVMValueRef ir_render_frame_address(CodeGen *g, IrExecutableGen *executa return LLVMBuildPtrToInt(g->builder, ptr_val, g->builtin_types.entry_usize->llvm_type, ""); } -static LLVMValueRef ir_render_handle(CodeGen *g, IrExecutableGen *executable, IrInstGenFrameHandle *instruction) { +static LLVMValueRef ir_render_handle(CodeGen *g, Stage1Air *executable, IrInstGenFrameHandle *instruction) { return g->cur_frame_ptr; } @@ -6053,7 +6053,7 @@ static LLVMValueRef render_shl_with_overflow(CodeGen *g, IrInstGenOverflowOp *in return overflow_bit; } -static LLVMValueRef ir_render_overflow_op(CodeGen *g, IrExecutableGen *executable, IrInstGenOverflowOp *instruction) { +static LLVMValueRef ir_render_overflow_op(CodeGen *g, Stage1Air *executable, IrInstGenOverflowOp *instruction) { AddSubMul add_sub_mul; switch (instruction->op) { case IrOverflowOpAdd: @@ -6091,7 +6091,7 @@ static LLVMValueRef ir_render_overflow_op(CodeGen *g, IrExecutableGen *executabl return overflow_bit; } -static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutableGen *executable, IrInstGenTestErr *instruction) { +static LLVMValueRef ir_render_test_err(CodeGen *g, Stage1Air *executable, IrInstGenTestErr *instruction) { ZigType *err_union_type = instruction->err_union->value->type; ZigType *payload_type = err_union_type->data.error_union.payload_type; LLVMValueRef err_union_handle = ir_llvm_value(g, instruction->err_union); @@ -6108,7 +6108,7 @@ static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutableGen *executable, return LLVMBuildICmp(g->builder, LLVMIntNE, err_val, zero, ""); } -static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutableGen *executable, +static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, Stage1Air *executable, IrInstGenUnwrapErrCode *instruction) { if (instruction->base.value->special != ConstValSpecialRuntime) @@ -6128,7 +6128,7 @@ static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutableGen *execu } } -static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutableGen *executable, +static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, Stage1Air *executable, IrInstGenUnwrapErrPayload *instruction) { Error err; @@ -6197,7 +6197,7 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutableGen *ex } } -static LLVMValueRef ir_render_optional_wrap(CodeGen *g, IrExecutableGen *executable, IrInstGenOptionalWrap *instruction) { +static LLVMValueRef ir_render_optional_wrap(CodeGen *g, Stage1Air *executable, IrInstGenOptionalWrap *instruction) { ZigType *wanted_type = instruction->base.value->type; assert(wanted_type->id == ZigTypeIdOptional); @@ -6233,7 +6233,7 @@ static LLVMValueRef ir_render_optional_wrap(CodeGen *g, IrExecutableGen *executa return result_loc; } -static LLVMValueRef ir_render_err_wrap_code(CodeGen *g, IrExecutableGen *executable, IrInstGenErrWrapCode *instruction) { +static LLVMValueRef ir_render_err_wrap_code(CodeGen *g, Stage1Air *executable, IrInstGenErrWrapCode *instruction) { ZigType *wanted_type = instruction->base.value->type; assert(wanted_type->id == ZigTypeIdErrorUnion); @@ -6253,7 +6253,7 @@ static LLVMValueRef ir_render_err_wrap_code(CodeGen *g, IrExecutableGen *executa return result_loc; } -static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, IrExecutableGen *executable, IrInstGenErrWrapPayload *instruction) { +static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, Stage1Air *executable, IrInstGenErrWrapPayload *instruction) { ZigType *wanted_type = instruction->base.value->type; assert(wanted_type->id == ZigTypeIdErrorUnion); @@ -6284,7 +6284,7 @@ static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, IrExecutableGen *exec return result_loc; } -static LLVMValueRef ir_render_union_tag(CodeGen *g, IrExecutableGen *executable, IrInstGenUnionTag *instruction) { +static LLVMValueRef ir_render_union_tag(CodeGen *g, Stage1Air *executable, IrInstGenUnionTag *instruction) { ZigType *union_type = instruction->value->value->type; ZigType *tag_type = union_type->data.unionation.tag_type; @@ -6302,14 +6302,14 @@ static LLVMValueRef ir_render_union_tag(CodeGen *g, IrExecutableGen *executable, return get_handle_value(g, tag_field_ptr, tag_type, ptr_type); } -static LLVMValueRef ir_render_panic(CodeGen *g, IrExecutableGen *executable, IrInstGenPanic *instruction) { +static LLVMValueRef ir_render_panic(CodeGen *g, Stage1Air *executable, IrInstGenPanic *instruction) { bool is_llvm_alloca; LLVMValueRef err_ret_trace_val = get_cur_err_ret_trace_val(g, instruction->base.base.scope, &is_llvm_alloca); gen_panic(g, ir_llvm_value(g, instruction->msg), err_ret_trace_val, is_llvm_alloca); return nullptr; } -static LLVMValueRef ir_render_atomic_rmw(CodeGen *g, IrExecutableGen *executable, +static LLVMValueRef ir_render_atomic_rmw(CodeGen *g, Stage1Air *executable, IrInstGenAtomicRmw *instruction) { bool is_signed; @@ -6354,7 +6354,7 @@ static LLVMValueRef ir_render_atomic_rmw(CodeGen *g, IrExecutableGen *executable return LLVMBuildIntToPtr(g->builder, uncasted_result, get_llvm_type(g, operand_type), ""); } -static LLVMValueRef ir_render_atomic_load(CodeGen *g, IrExecutableGen *executable, +static LLVMValueRef ir_render_atomic_load(CodeGen *g, Stage1Air *executable, IrInstGenAtomicLoad *instruction) { LLVMAtomicOrdering ordering = to_LLVMAtomicOrdering(instruction->ordering); @@ -6375,7 +6375,7 @@ static LLVMValueRef ir_render_atomic_load(CodeGen *g, IrExecutableGen *executabl return load_inst; } -static LLVMValueRef ir_render_atomic_store(CodeGen *g, IrExecutableGen *executable, +static LLVMValueRef ir_render_atomic_store(CodeGen *g, Stage1Air *executable, IrInstGenAtomicStore *instruction) { LLVMAtomicOrdering ordering = to_LLVMAtomicOrdering(instruction->ordering); @@ -6398,13 +6398,13 @@ static LLVMValueRef ir_render_atomic_store(CodeGen *g, IrExecutableGen *executab return nullptr; } -static LLVMValueRef ir_render_float_op(CodeGen *g, IrExecutableGen *executable, IrInstGenFloatOp *instruction) { +static LLVMValueRef ir_render_float_op(CodeGen *g, Stage1Air *executable, IrInstGenFloatOp *instruction) { LLVMValueRef operand = ir_llvm_value(g, instruction->operand); LLVMValueRef fn_val = get_float_fn(g, instruction->base.value->type, ZigLLVMFnIdFloatOp, instruction->fn_id); return LLVMBuildCall(g->builder, fn_val, &operand, 1, ""); } -static LLVMValueRef ir_render_mul_add(CodeGen *g, IrExecutableGen *executable, IrInstGenMulAdd *instruction) { +static LLVMValueRef ir_render_mul_add(CodeGen *g, Stage1Air *executable, IrInstGenMulAdd *instruction) { LLVMValueRef op1 = ir_llvm_value(g, instruction->op1); LLVMValueRef op2 = ir_llvm_value(g, instruction->op2); LLVMValueRef op3 = ir_llvm_value(g, instruction->op3); @@ -6419,7 +6419,7 @@ static LLVMValueRef ir_render_mul_add(CodeGen *g, IrExecutableGen *executable, I return LLVMBuildCall(g->builder, fn_val, args, 3, ""); } -static LLVMValueRef ir_render_bswap(CodeGen *g, IrExecutableGen *executable, IrInstGenBswap *instruction) { +static LLVMValueRef ir_render_bswap(CodeGen *g, Stage1Air *executable, IrInstGenBswap *instruction) { LLVMValueRef op = ir_llvm_value(g, instruction->op); ZigType *expr_type = instruction->base.value->type; bool is_vector = expr_type->id == ZigTypeIdVector; @@ -6453,7 +6453,7 @@ static LLVMValueRef ir_render_bswap(CodeGen *g, IrExecutableGen *executable, IrI return LLVMBuildTrunc(g->builder, shifted, get_llvm_type(g, expr_type), ""); } -static LLVMValueRef ir_render_extern(CodeGen *g, IrExecutableGen *executable, +static LLVMValueRef ir_render_extern(CodeGen *g, Stage1Air *executable, IrInstGenExtern *instruction) { ZigType *expr_type = instruction->base.value->type; @@ -6477,7 +6477,7 @@ static LLVMValueRef ir_render_extern(CodeGen *g, IrExecutableGen *executable, return LLVMBuildBitCast(g->builder, global_value, get_llvm_type(g, expr_type), ""); } -static LLVMValueRef ir_render_bit_reverse(CodeGen *g, IrExecutableGen *executable, IrInstGenBitReverse *instruction) { +static LLVMValueRef ir_render_bit_reverse(CodeGen *g, Stage1Air *executable, IrInstGenBitReverse *instruction) { LLVMValueRef op = ir_llvm_value(g, instruction->op); ZigType *int_type = instruction->base.value->type; assert(int_type->id == ZigTypeIdInt); @@ -6485,7 +6485,7 @@ static LLVMValueRef ir_render_bit_reverse(CodeGen *g, IrExecutableGen *executabl return LLVMBuildCall(g->builder, fn_val, &op, 1, ""); } -static LLVMValueRef ir_render_vector_to_array(CodeGen *g, IrExecutableGen *executable, +static LLVMValueRef ir_render_vector_to_array(CodeGen *g, Stage1Air *executable, IrInstGenVectorToArray *instruction) { ZigType *array_type = instruction->base.value->type; @@ -6519,7 +6519,7 @@ static LLVMValueRef ir_render_vector_to_array(CodeGen *g, IrExecutableGen *execu return result_loc; } -static LLVMValueRef ir_render_array_to_vector(CodeGen *g, IrExecutableGen *executable, +static LLVMValueRef ir_render_array_to_vector(CodeGen *g, Stage1Air *executable, IrInstGenArrayToVector *instruction) { ZigType *vector_type = instruction->base.value->type; @@ -6556,7 +6556,7 @@ static LLVMValueRef ir_render_array_to_vector(CodeGen *g, IrExecutableGen *execu } } -static LLVMValueRef ir_render_assert_zero(CodeGen *g, IrExecutableGen *executable, +static LLVMValueRef ir_render_assert_zero(CodeGen *g, Stage1Air *executable, IrInstGenAssertZero *instruction) { LLVMValueRef target = ir_llvm_value(g, instruction->target); @@ -6567,7 +6567,7 @@ static LLVMValueRef ir_render_assert_zero(CodeGen *g, IrExecutableGen *executabl return nullptr; } -static LLVMValueRef ir_render_assert_non_null(CodeGen *g, IrExecutableGen *executable, +static LLVMValueRef ir_render_assert_non_null(CodeGen *g, Stage1Air *executable, IrInstGenAssertNonNull *instruction) { LLVMValueRef target = ir_llvm_value(g, instruction->target); @@ -6592,7 +6592,7 @@ static LLVMValueRef ir_render_assert_non_null(CodeGen *g, IrExecutableGen *execu return nullptr; } -static LLVMValueRef ir_render_suspend_begin(CodeGen *g, IrExecutableGen *executable, +static LLVMValueRef ir_render_suspend_begin(CodeGen *g, Stage1Air *executable, IrInstGenSuspendBegin *instruction) { if (fn_is_async(g->cur_fn)) { @@ -6601,7 +6601,7 @@ static LLVMValueRef ir_render_suspend_begin(CodeGen *g, IrExecutableGen *executa return nullptr; } -static LLVMValueRef ir_render_suspend_finish(CodeGen *g, IrExecutableGen *executable, +static LLVMValueRef ir_render_suspend_finish(CodeGen *g, Stage1Air *executable, IrInstGenSuspendFinish *instruction) { LLVMBuildRetVoid(g->builder); @@ -6653,7 +6653,7 @@ static LLVMValueRef gen_await_early_return(CodeGen *g, IrInstGen *source_instr, } } -static LLVMValueRef ir_render_await(CodeGen *g, IrExecutableGen *executable, IrInstGenAwait *instruction) { +static LLVMValueRef ir_render_await(CodeGen *g, Stage1Air *executable, IrInstGenAwait *instruction) { LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; LLVMValueRef zero = LLVMConstNull(usize_type_ref); LLVMValueRef target_frame_ptr = ir_llvm_value(g, instruction->frame); @@ -6740,7 +6740,7 @@ static LLVMValueRef ir_render_await(CodeGen *g, IrExecutableGen *executable, IrI return nullptr; } -static LLVMValueRef ir_render_resume(CodeGen *g, IrExecutableGen *executable, IrInstGenResume *instruction) { +static LLVMValueRef ir_render_resume(CodeGen *g, Stage1Air *executable, IrInstGenResume *instruction) { LLVMValueRef frame = ir_llvm_value(g, instruction->frame); ZigType *frame_type = instruction->frame->value->type; assert(frame_type->id == ZigTypeIdAnyFrame); @@ -6749,14 +6749,14 @@ static LLVMValueRef ir_render_resume(CodeGen *g, IrExecutableGen *executable, Ir return nullptr; } -static LLVMValueRef ir_render_frame_size(CodeGen *g, IrExecutableGen *executable, +static LLVMValueRef ir_render_frame_size(CodeGen *g, Stage1Air *executable, IrInstGenFrameSize *instruction) { LLVMValueRef fn_val = ir_llvm_value(g, instruction->fn); return gen_frame_size(g, fn_val); } -static LLVMValueRef ir_render_spill_begin(CodeGen *g, IrExecutableGen *executable, +static LLVMValueRef ir_render_spill_begin(CodeGen *g, Stage1Air *executable, IrInstGenSpillBegin *instruction) { if (!fn_is_async(g->cur_fn)) @@ -6776,7 +6776,7 @@ static LLVMValueRef ir_render_spill_begin(CodeGen *g, IrExecutableGen *executabl zig_unreachable(); } -static LLVMValueRef ir_render_spill_end(CodeGen *g, IrExecutableGen *executable, IrInstGenSpillEnd *instruction) { +static LLVMValueRef ir_render_spill_end(CodeGen *g, Stage1Air *executable, IrInstGenSpillEnd *instruction) { if (!fn_is_async(g->cur_fn)) return ir_llvm_value(g, instruction->begin->operand); @@ -6792,7 +6792,7 @@ static LLVMValueRef ir_render_spill_end(CodeGen *g, IrExecutableGen *executable, zig_unreachable(); } -static LLVMValueRef ir_render_vector_extract_elem(CodeGen *g, IrExecutableGen *executable, +static LLVMValueRef ir_render_vector_extract_elem(CodeGen *g, Stage1Air *executable, IrInstGenVectorExtractElem *instruction) { LLVMValueRef vector = ir_llvm_value(g, instruction->vector); @@ -6811,7 +6811,7 @@ static void set_debug_location(CodeGen *g, IrInstGen *instruction) { node_column_onebased(source_node), get_di_scope(g, scope)); } -static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutableGen *executable, IrInstGen *instruction) { +static LLVMValueRef ir_render_instruction(CodeGen *g, Stage1Air *executable, IrInstGen *instruction) { switch (instruction->id) { case IrInstGenIdInvalid: case IrInstGenIdConst: @@ -6999,7 +6999,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutableGen *executabl static void ir_render(CodeGen *g, ZigFn *fn_entry) { assert(fn_entry); - IrExecutableGen *executable = &fn_entry->analyzed_executable; + Stage1Air *executable = &fn_entry->analyzed_executable; assert(executable->basic_block_list.length > 0); for (size_t block_i = 0; block_i < executable->basic_block_list.length; block_i += 1) { @@ -7997,7 +7997,7 @@ static void generate_error_name_table(CodeGen *g) { } static void build_all_basic_blocks(CodeGen *g, ZigFn *fn) { - IrExecutableGen *executable = &fn->analyzed_executable; + Stage1Air *executable = &fn->analyzed_executable; assert(executable->basic_block_list.length > 0); LLVMValueRef fn_val = fn_llvm_value(g, fn); LLVMBasicBlockRef first_bb = nullptr; @@ -8380,7 +8380,7 @@ static void do_code_gen(CodeGen *g) { node_line_onebased(source_node), node_column_onebased(source_node), get_di_scope(g, fn_table_entry->child_scope)); } - IrExecutableGen *executable = &fn_table_entry->analyzed_executable; + Stage1Air *executable = &fn_table_entry->analyzed_executable; LLVMBasicBlockRef bad_resume_block = LLVMAppendBasicBlock(g->cur_fn_val, "BadResume"); LLVMPositionBuilderAtEnd(g->builder, bad_resume_block); gen_assertion_scope(g, PanicMsgIdBadResume, fn_table_entry->child_scope); diff --git a/src/stage1/ir.cpp b/src/stage1/ir.cpp index f143c101a0..be19e0c8d3 100644 --- a/src/stage1/ir.cpp +++ b/src/stage1/ir.cpp @@ -24,7 +24,7 @@ struct IrBuilderGen { CodeGen *codegen; - IrExecutableGen *exec; + Stage1Air *exec; IrBasicBlockGen *current_basic_block; // track for immediate post-analysis destruction @@ -46,6 +46,9 @@ struct IrAnalyze { size_t ref_count; size_t break_debug_id; // for debugging purposes IrInstGen *return_ptr; + Stage1Air *parent_exec; + size_t *backward_branch_count; + size_t *backward_branch_quota; // For the purpose of using in a debugger void dump(); @@ -672,7 +675,7 @@ static void ir_inst_gen_append(IrBasicBlockGen *basic_block, IrInstGen *instruct basic_block->instruction_list.append(instruction); } -static size_t exec_next_debug_id_gen(IrExecutableGen *exec) { +static size_t exec_next_debug_id_gen(Stage1Air *exec) { size_t result = exec->next_debug_id; exec->next_debug_id += 1; return result; @@ -716,7 +719,7 @@ ZigType *ir_analyze_type_expr(IrAnalyze *ira, Scope *scope, AstNode *node) { create_result_ptr(ira->codegen, ira->codegen->builtin_types.entry_type, &result, &result_ptr); if ((err = ir_eval_const_value(ira->codegen, scope, node, result_ptr, - ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, + ira->backward_branch_count, ira->backward_branch_quota, nullptr, nullptr, node, nullptr, ira->new_irb.exec, nullptr, UndefBad))) { return ira->codegen->builtin_types.entry_invalid; @@ -2512,7 +2515,7 @@ static ZigType *make_err_set_with_one_item(CodeGen *g, Scope *parent_scope, AstN return err_set_type; } -static void invalidate_exec_gen(IrExecutableGen *exec, ErrorMsg *msg) { +static void invalidate_exec_gen(Stage1Air *exec, ErrorMsg *msg) { if (exec->first_err_trace_msg != nullptr) return; @@ -2527,7 +2530,7 @@ static void invalidate_exec_gen(IrExecutableGen *exec, ErrorMsg *msg) { } -static ErrorMsg *exec_add_error_node_gen(CodeGen *codegen, IrExecutableGen *exec, AstNode *source_node, Buf *msg) { +static ErrorMsg *exec_add_error_node_gen(CodeGen *codegen, Stage1Air *exec, AstNode *source_node, Buf *msg) { ErrorMsg *err_msg = add_node_error(codegen, source_node, msg); invalidate_exec_gen(exec, err_msg); if (exec->parent_exec) { @@ -2601,7 +2604,7 @@ ZigValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ZigValue *const_va return val; } -static Error ir_exec_scan_for_side_effects(CodeGen *codegen, IrExecutableGen *exec) { +static Error ir_exec_scan_for_side_effects(CodeGen *codegen, Stage1Air *exec) { IrBasicBlockGen *bb = exec->basic_block_list.at(0); for (size_t i = 0; i < bb->instruction_list.length; i += 1) { IrInstGen *instruction = bb->instruction_list.at(i); @@ -5425,8 +5428,8 @@ static IrInstGen *ir_unreach_error(IrAnalyze *ira) { } static bool ir_emit_backward_branch(IrAnalyze *ira, IrInst* source_instruction) { - size_t *bbc = ira->new_irb.exec->backward_branch_count; - size_t *quota = ira->new_irb.exec->backward_branch_quota; + size_t *bbc = ira->backward_branch_count; + size_t *quota = ira->backward_branch_quota; // If we're already over quota, we've already given an error message for this. if (*bbc > *quota) { @@ -5532,7 +5535,7 @@ static IrInstGen *ir_get_const_ptr(IrAnalyze *ira, IrInst *instruction, return const_instr; } -static Error ir_resolve_const_val(CodeGen *codegen, IrExecutableGen *exec, AstNode *source_node, +static Error ir_resolve_const_val(CodeGen *codegen, Stage1Air *exec, AstNode *source_node, ZigValue *val, UndefAllowed undef_allowed) { Error err; @@ -5579,7 +5582,7 @@ static ZigValue *ir_resolve_const(IrAnalyze *ira, IrInstGen *value, UndefAllowed Error ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, ZigValue *return_ptr, size_t *backward_branch_count, size_t *backward_branch_quota, ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name, - IrExecutableGen *parent_exec, AstNode *expected_type_source_node, UndefAllowed undef_allowed) + Stage1Air *parent_exec, AstNode *expected_type_source_node, UndefAllowed undef_allowed) { Error err; @@ -5590,7 +5593,6 @@ Error ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, Stage1Zir *ir_executable = heap::c_allocator.create(); ir_executable->source_node = source_node; - ir_executable->parent_exec = parent_exec; ir_executable->name = exec_name; ir_executable->is_inline = true; ir_executable->fn_entry = fn_entry; @@ -5610,7 +5612,7 @@ Error ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, ir_print_src(codegen, stderr, ir_executable, 2); fprintf(stderr, "}\n"); } - IrExecutableGen *analyzed_executable = heap::c_allocator.create(); + Stage1Air *analyzed_executable = heap::c_allocator.create(); analyzed_executable->source_node = source_node; analyzed_executable->parent_exec = parent_exec; analyzed_executable->source_exec = ir_executable; @@ -5618,10 +5620,9 @@ Error ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, analyzed_executable->is_inline = true; analyzed_executable->fn_entry = fn_entry; analyzed_executable->c_import_buf = c_import_buf; - analyzed_executable->backward_branch_count = backward_branch_count; - analyzed_executable->backward_branch_quota = backward_branch_quota; analyzed_executable->begin_scope = scope; ZigType *result_type = ir_analyze(codegen, ir_executable, analyzed_executable, + backward_branch_count, backward_branch_quota, return_ptr->type->data.pointer.child_type, expected_type_source_node, return_ptr); if (type_is_invalid(result_type)) { return ErrorSemanticAnalyzeFail; @@ -5663,7 +5664,7 @@ static ErrorTableEntry *ir_resolve_error(IrAnalyze *ira, IrInstGen *err_value) { return const_val->data.x_err_set; } -static ZigType *ir_resolve_const_type(CodeGen *codegen, IrExecutableGen *exec, AstNode *source_node, +static ZigType *ir_resolve_const_type(CodeGen *codegen, Stage1Air *exec, AstNode *source_node, ZigValue *val) { Error err; @@ -8071,7 +8072,7 @@ static IrInstGen *ir_get_deref(IrAnalyze *ira, IrInst* source_instruction, IrIns return ir_build_load_ptr_gen(ira, source_instruction, ptr, child_type, result_loc_inst); } -static bool ir_resolve_const_align(CodeGen *codegen, IrExecutableGen *exec, AstNode *source_node, +static bool ir_resolve_const_align(CodeGen *codegen, Stage1Air *exec, AstNode *source_node, ZigValue *const_val, uint32_t *out) { Error err; @@ -12752,7 +12753,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, create_result_ptr(ira->codegen, return_type, &result, &result_ptr); if ((err = ir_eval_const_value(ira->codegen, exec_scope, body_node, result_ptr, - ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, + ira->backward_branch_count, ira->backward_branch_quota, fn_entry, nullptr, source_instr->source_node, nullptr, ira->new_irb.exec, return_type_node, UndefOk))) { @@ -12869,7 +12870,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, create_result_ptr(ira->codegen, get_align_amt_type(ira->codegen), &align_result, &result_ptr); if ((err = ir_eval_const_value(ira->codegen, impl_fn->child_scope, fn_proto_node->data.fn_proto.align_expr, result_ptr, - ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, + ira->backward_branch_count, ira->backward_branch_quota, nullptr, nullptr, fn_proto_node->data.fn_proto.align_expr, nullptr, ira->new_irb.exec, nullptr, UndefBad))) { @@ -12934,11 +12935,9 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, return ira->codegen->invalid_inst_gen; impl_fn->ir_executable->source_node = source_instr->source_node; - impl_fn->ir_executable->parent_exec = ira->new_irb.exec; impl_fn->analyzed_executable.source_node = source_instr->source_node; impl_fn->analyzed_executable.parent_exec = ira->new_irb.exec; - impl_fn->analyzed_executable.backward_branch_quota = ira->new_irb.exec->backward_branch_quota; - impl_fn->analyzed_executable.is_generic_instantiation = true; + impl_fn->branch_quota = *ira->backward_branch_quota; ira->codegen->fn_defs.append(impl_fn); } @@ -18980,8 +18979,8 @@ static IrInstGen *ir_analyze_instruction_set_eval_branch_quota(IrAnalyze *ira, if (!ir_resolve_unsigned(ira, instruction->new_quota->child, ira->codegen->builtin_types.entry_u32, &new_quota)) return ira->codegen->invalid_inst_gen; - if (new_quota > *ira->new_irb.exec->backward_branch_quota) { - *ira->new_irb.exec->backward_branch_quota = new_quota; + if (new_quota > *ira->backward_branch_quota) { + *ira->backward_branch_quota = new_quota; } return ir_const_void(ira, &instruction->base.base); @@ -19015,7 +19014,7 @@ static IrInstGen *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstSrcCImpo ZigValue *result_ptr; create_result_ptr(ira->codegen, void_type, &cimport_result, &result_ptr); if ((err = ir_eval_const_value(ira->codegen, &cimport_scope->base, block_node, result_ptr, - ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, nullptr, + ira->backward_branch_count, ira->backward_branch_quota, nullptr, &cimport_scope->buf, block_node, nullptr, nullptr, nullptr, UndefBad))) { return ira->codegen->invalid_inst_gen; @@ -24467,25 +24466,27 @@ static IrInstGen *ir_analyze_instruction_base(IrAnalyze *ira, IrInstSrc *instruc } // This function attempts to evaluate IR code while doing type checking and other analysis. -// It emits to a new IrExecutableGen which is partially evaluated IR code. -ZigType *ir_analyze(CodeGen *codegen, Stage1Zir *old_exec, IrExecutableGen *new_exec, +// It emits to a new Stage1Air which is partially evaluated IR code. +ZigType *ir_analyze(CodeGen *codegen, Stage1Zir *stage1_zir, Stage1Air *stage1_air, + size_t *backward_branch_count, size_t *backward_branch_quota, ZigType *expected_type, AstNode *expected_type_source_node, ZigValue *result_ptr) { - assert(old_exec->first_err_trace_msg == nullptr); + assert(stage1_zir->first_err_trace_msg == nullptr); assert(expected_type == nullptr || !type_is_invalid(expected_type)); IrAnalyze *ira = heap::c_allocator.create(); + ira->backward_branch_count = backward_branch_count; + ira->backward_branch_quota = backward_branch_quota; ira->ref_count = 1; - old_exec->analysis = ira; ira->codegen = codegen; ira->explicit_return_type = expected_type; ira->explicit_return_type_source_node = expected_type_source_node; - ira->zir = old_exec; + ira->zir = stage1_zir; ira->new_irb.codegen = codegen; - ira->new_irb.exec = new_exec; + ira->new_irb.exec = stage1_air; IrBasicBlockSrc *old_entry_bb = ira->zir->basic_block_list.at(0); IrBasicBlockGen *new_entry_bb = ir_get_new_bb(ira, old_entry_bb, nullptr); @@ -24497,13 +24498,13 @@ ZigType *ir_analyze(CodeGen *codegen, Stage1Zir *old_exec, IrExecutableGen *new_ if (result_ptr != nullptr) { assert(result_ptr->type->id == ZigTypeIdPointer); IrInstGenConst *const_inst = ir_create_inst_noval( - &ira->new_irb, new_exec->begin_scope, new_exec->source_node); + &ira->new_irb, stage1_air->begin_scope, stage1_air->source_node); const_inst->base.value = result_ptr; ira->return_ptr = &const_inst->base; } else { - assert(new_exec->begin_scope != nullptr); - assert(new_exec->source_node != nullptr); - ira->return_ptr = ir_build_return_ptr(ira, new_exec->begin_scope, new_exec->source_node, + assert(stage1_air->begin_scope != nullptr); + assert(stage1_air->source_node != nullptr); + ira->return_ptr = ir_build_return_ptr(ira, stage1_air->begin_scope, stage1_air->source_node, get_pointer_to_type(codegen, expected_type, false)); } @@ -24531,16 +24532,16 @@ ZigType *ir_analyze(CodeGen *codegen, Stage1Zir *old_exec, IrExecutableGen *new_ fprintf(stderr, "-> (invalid)"); } - if (new_exec->first_err_trace_msg != nullptr) { - ira->codegen->trace_err = new_exec->first_err_trace_msg; + if (stage1_air->first_err_trace_msg != nullptr) { + ira->codegen->trace_err = stage1_air->first_err_trace_msg; } else { - new_exec->first_err_trace_msg = ira->codegen->trace_err; + stage1_air->first_err_trace_msg = ira->codegen->trace_err; } - if (new_exec->first_err_trace_msg != nullptr && + if (stage1_air->first_err_trace_msg != nullptr && !old_instruction->base.source_node->already_traced_this_node) { old_instruction->base.source_node->already_traced_this_node = true; - new_exec->first_err_trace_msg = add_error_note(ira->codegen, new_exec->first_err_trace_msg, + stage1_air->first_err_trace_msg = add_error_note(ira->codegen, stage1_air->first_err_trace_msg, old_instruction->base.source_node, buf_create_from_str("referenced here")); } return ira->codegen->builtin_types.entry_invalid; @@ -24566,14 +24567,14 @@ ZigType *ir_analyze(CodeGen *codegen, Stage1Zir *old_exec, IrExecutableGen *new_ } ZigType *res_type; - if (new_exec->first_err_trace_msg != nullptr) { - codegen->trace_err = new_exec->first_err_trace_msg; - if (codegen->trace_err != nullptr && new_exec->source_node != nullptr && - !new_exec->source_node->already_traced_this_node) + if (stage1_air->first_err_trace_msg != nullptr) { + codegen->trace_err = stage1_air->first_err_trace_msg; + if (codegen->trace_err != nullptr && stage1_air->source_node != nullptr && + !stage1_air->source_node->already_traced_this_node) { - new_exec->source_node->already_traced_this_node = true; + stage1_air->source_node->already_traced_this_node = true; codegen->trace_err = add_error_note(codegen, codegen->trace_err, - new_exec->source_node, buf_create_from_str("referenced here")); + stage1_air->source_node, buf_create_from_str("referenced here")); } res_type = ira->codegen->builtin_types.entry_invalid; } else if (ira->src_implicit_return_type_list.length == 0) { diff --git a/src/stage1/ir.hpp b/src/stage1/ir.hpp index a20a1782c1..eece7e298f 100644 --- a/src/stage1/ir.hpp +++ b/src/stage1/ir.hpp @@ -16,12 +16,13 @@ IrInstGen *ir_create_alloca(CodeGen *g, Scope *scope, AstNode *source_node, ZigF Error ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, ZigValue *return_ptr, size_t *backward_branch_count, size_t *backward_branch_quota, ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name, - IrExecutableGen *parent_exec, AstNode *expected_type_source_node, UndefAllowed undef); + Stage1Air *parent_exec, AstNode *expected_type_source_node, UndefAllowed undef); Error ir_resolve_lazy(CodeGen *codegen, AstNode *source_node, ZigValue *val); -ZigType *ir_analyze(CodeGen *g, Stage1Zir *old_executable, IrExecutableGen *new_executable, - ZigType *expected_type, AstNode *expected_type_source_node, ZigValue *return_ptr); +ZigType *ir_analyze(CodeGen *codegen, Stage1Zir *stage1_zir, Stage1Air *stage1_air, + size_t *backward_branch_count, size_t *backward_branch_quota, + ZigType *expected_type, AstNode *expected_type_source_node, ZigValue *result_ptr); bool ir_inst_gen_has_side_effects(IrInstGen *inst); bool ir_inst_src_has_side_effects(IrInstSrc *inst); diff --git a/src/stage1/ir_print.cpp b/src/stage1/ir_print.cpp index 8820db81d4..1fdf0e14d5 100644 --- a/src/stage1/ir_print.cpp +++ b/src/stage1/ir_print.cpp @@ -3408,7 +3408,7 @@ void ir_print_src(CodeGen *codegen, FILE *f, Stage1Zir *executable, int indent_s } } -void ir_print_gen(CodeGen *codegen, FILE *f, IrExecutableGen *executable, int indent_size) { +void ir_print_gen(CodeGen *codegen, FILE *f, Stage1Air *executable, int indent_size) { IrPrintGen ir_print = {}; IrPrintGen *irp = &ir_print; irp->codegen = codegen; diff --git a/src/stage1/ir_print.hpp b/src/stage1/ir_print.hpp index a20ef8808c..bec75be515 100644 --- a/src/stage1/ir_print.hpp +++ b/src/stage1/ir_print.hpp @@ -13,7 +13,7 @@ #include void ir_print_src(CodeGen *codegen, FILE *f, Stage1Zir *executable, int indent_size); -void ir_print_gen(CodeGen *codegen, FILE *f, IrExecutableGen *executable, int indent_size); +void ir_print_gen(CodeGen *codegen, FILE *f, Stage1Air *executable, int indent_size); void ir_print_inst_src(CodeGen *codegen, FILE *f, IrInstSrc *inst, int indent_size); void ir_print_inst_gen(CodeGen *codegen, FILE *f, IrInstGen *inst, int indent_size); void ir_print_basic_block_src(CodeGen *codegen, FILE *f, IrBasicBlockSrc *bb, int indent_size); From 2440c08ab02f7d7b82deb3bd4eeaafb33483307f Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 27 May 2021 20:36:37 -0700 Subject: [PATCH 05/14] stage1: move next_debug_id from Stage1Zir to IrBuilderSrc Part of an effort to make Stage1Zir immutable. --- src/stage1/all_types.hpp | 2 -- src/stage1/astgen.cpp | 17 +++++++++-------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/stage1/all_types.hpp b/src/stage1/all_types.hpp index 56763b4d7f..90913ed6be 100644 --- a/src/stage1/all_types.hpp +++ b/src/stage1/all_types.hpp @@ -114,8 +114,6 @@ struct Stage1Zir { ZigList basic_block_list; Buf *name; ZigFn *name_fn; - size_t mem_slot_count; - size_t next_debug_id; ZigFn *fn_entry; Buf *c_import_buf; AstNode *source_node; diff --git a/src/stage1/astgen.cpp b/src/stage1/astgen.cpp index 11c82701f5..a05a92d8dc 100644 --- a/src/stage1/astgen.cpp +++ b/src/stage1/astgen.cpp @@ -16,6 +16,7 @@ struct IrBuilderSrc { Stage1Zir *exec; IrBasicBlockSrc *current_basic_block; AstNode *main_block_node; + size_t next_debug_id; }; static IrInstSrc *ir_gen_node(IrBuilderSrc *irb, AstNode *node, Scope *scope); @@ -361,9 +362,9 @@ static void ir_instruction_append(IrBasicBlockSrc *basic_block, IrInstSrc *instr basic_block->instruction_list.append(instruction); } -static size_t exec_next_debug_id(Stage1Zir *exec) { - size_t result = exec->next_debug_id; - exec->next_debug_id += 1; +static size_t irb_next_debug_id(IrBuilderSrc *irb) { + size_t result = irb->next_debug_id; + irb->next_debug_id += 1; return result; } @@ -393,7 +394,7 @@ static IrBasicBlockSrc *ir_create_basic_block(IrBuilderSrc *irb, Scope *scope, c IrBasicBlockSrc *result = heap::c_allocator.create(); result->scope = scope; result->name_hint = name_hint; - result->debug_id = exec_next_debug_id(irb->exec); + result->debug_id = irb_next_debug_id(irb); result->index = UINT32_MAX; // set later return result; } @@ -936,7 +937,7 @@ static T *ir_create_instruction(IrBuilderSrc *irb, Scope *scope, AstNode *source special_instruction->base.id = ir_inst_id(special_instruction); special_instruction->base.base.scope = scope; special_instruction->base.base.source_node = source_node; - special_instruction->base.base.debug_id = exec_next_debug_id(irb->exec); + special_instruction->base.base.debug_id = irb_next_debug_id(irb); special_instruction->base.owner_bb = irb->current_basic_block; return special_instruction; } @@ -1325,7 +1326,7 @@ static IrInstSrc *ir_build_ptr_type_simple(IrBuilderSrc *irb, Scope *scope, AstN inst->base.id = is_const ? IrInstSrcIdPtrTypeSimpleConst : IrInstSrcIdPtrTypeSimple; inst->base.base.scope = scope; inst->base.base.source_node = source_node; - inst->base.base.debug_id = exec_next_debug_id(irb->exec); + inst->base.base.debug_id = irb_next_debug_id(irb); inst->base.owner_bb = irb->current_basic_block; ir_instruction_append(irb->current_basic_block, &inst->base); @@ -2393,7 +2394,7 @@ static IrInstSrc *ir_build_check_switch_prongs(IrBuilderSrc *irb, Scope *scope, IrInstSrcIdCheckSwitchProngsUnderYes : IrInstSrcIdCheckSwitchProngsUnderNo; instruction->base.base.scope = scope; instruction->base.base.source_node = source_node; - instruction->base.base.debug_id = exec_next_debug_id(irb->exec); + instruction->base.base.debug_id = irb_next_debug_id(irb); instruction->base.owner_bb = irb->current_basic_block; ir_instruction_append(irb->current_basic_block, &instruction->base); @@ -2586,7 +2587,7 @@ static IrInstSrc *ir_build_arg_type(IrBuilderSrc *irb, Scope *scope, AstNode *so IrInstSrcIdArgTypeAllowVarTrue : IrInstSrcIdArgTypeAllowVarFalse; instruction->base.base.scope = scope; instruction->base.base.source_node = source_node; - instruction->base.base.debug_id = exec_next_debug_id(irb->exec); + instruction->base.base.debug_id = irb_next_debug_id(irb); instruction->base.owner_bb = irb->current_basic_block; ir_instruction_append(irb->current_basic_block, &instruction->base); From 42f4ee0aebf274e74ece73157a63bbc0c6383c31 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 27 May 2021 20:42:06 -0700 Subject: [PATCH 06/14] stage1: rename IrBuilderSrc to Stage1AstGen --- src/stage1/astgen.cpp | 4524 ++++++++++++++++++++--------------------- 1 file changed, 2262 insertions(+), 2262 deletions(-) diff --git a/src/stage1/astgen.cpp b/src/stage1/astgen.cpp index a05a92d8dc..a14eb02cc2 100644 --- a/src/stage1/astgen.cpp +++ b/src/stage1/astgen.cpp @@ -11,7 +11,7 @@ #include "os.hpp" #include "parser.hpp" -struct IrBuilderSrc { +struct Stage1AstGen { CodeGen *codegen; Stage1Zir *exec; IrBasicBlockSrc *current_basic_block; @@ -19,22 +19,22 @@ struct IrBuilderSrc { size_t next_debug_id; }; -static IrInstSrc *ir_gen_node(IrBuilderSrc *irb, AstNode *node, Scope *scope); -static IrInstSrc *ir_gen_node_extra(IrBuilderSrc *irb, AstNode *node, Scope *scope, LVal lval, +static IrInstSrc *ir_gen_node(Stage1AstGen *ag, AstNode *node, Scope *scope); +static IrInstSrc *ir_gen_node_extra(Stage1AstGen *ag, AstNode *node, Scope *scope, LVal lval, ResultLoc *result_loc); -static IrInstSrc *ir_lval_wrap(IrBuilderSrc *irb, Scope *scope, IrInstSrc *value, LVal lval, +static IrInstSrc *ir_lval_wrap(Stage1AstGen *ag, Scope *scope, IrInstSrc *value, LVal lval, ResultLoc *result_loc); -static IrInstSrc *ir_expr_wrap(IrBuilderSrc *irb, Scope *scope, IrInstSrc *inst, +static IrInstSrc *ir_expr_wrap(Stage1AstGen *ag, Scope *scope, IrInstSrc *inst, ResultLoc *result_loc); -static IrInstSrc *ir_gen_union_init_expr(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_gen_union_init_expr(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *union_type, IrInstSrc *field_name, AstNode *expr_node, LVal lval, ResultLoc *parent_result_loc); -static ResultLocCast *ir_build_cast_result_loc(IrBuilderSrc *irb, IrInstSrc *dest_type, +static ResultLocCast *ir_build_cast_result_loc(Stage1AstGen *ag, IrInstSrc *dest_type, ResultLoc *parent_result_loc); -static ZigVar *ir_create_var(IrBuilderSrc *irb, AstNode *node, Scope *scope, Buf *name, +static ZigVar *ir_create_var(Stage1AstGen *ag, AstNode *node, Scope *scope, Buf *name, bool src_is_const, bool gen_is_const, bool is_shadowable, IrInstSrc *is_comptime); -static void build_decl_var_and_init(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static void build_decl_var_and_init(Stage1AstGen *ag, Scope *scope, AstNode *source_node, ZigVar *var, IrInstSrc *init, const char *name_hint, IrInstSrc *is_comptime); static void ir_assert_impl(bool ok, IrInst *source_instruction, char const *file, unsigned int line) { @@ -362,9 +362,9 @@ static void ir_instruction_append(IrBasicBlockSrc *basic_block, IrInstSrc *instr basic_block->instruction_list.append(instruction); } -static size_t irb_next_debug_id(IrBuilderSrc *irb) { - size_t result = irb->next_debug_id; - irb->next_debug_id += 1; +static size_t irb_next_debug_id(Stage1AstGen *ag) { + size_t result = ag->next_debug_id; + ag->next_debug_id += 1; return result; } @@ -390,11 +390,11 @@ static void ir_ref_instruction(IrInstSrc *instruction, IrBasicBlockSrc *cur_bb) } } -static IrBasicBlockSrc *ir_create_basic_block(IrBuilderSrc *irb, Scope *scope, const char *name_hint) { +static IrBasicBlockSrc *ir_create_basic_block(Stage1AstGen *ag, Scope *scope, const char *name_hint) { IrBasicBlockSrc *result = heap::c_allocator.create(); result->scope = scope; result->name_hint = name_hint; - result->debug_id = irb_next_debug_id(irb); + result->debug_id = irb_next_debug_id(ag); result->index = UINT32_MAX; // set later return result; } @@ -932,208 +932,208 @@ static constexpr IrInstSrcId ir_inst_id(IrInstSrcSrc *) { } template -static T *ir_create_instruction(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { +static T *ir_create_instruction(Stage1AstGen *ag, Scope *scope, AstNode *source_node) { T *special_instruction = heap::c_allocator.create(); special_instruction->base.id = ir_inst_id(special_instruction); special_instruction->base.base.scope = scope; special_instruction->base.base.source_node = source_node; - special_instruction->base.base.debug_id = irb_next_debug_id(irb); - special_instruction->base.owner_bb = irb->current_basic_block; + special_instruction->base.base.debug_id = irb_next_debug_id(ag); + special_instruction->base.owner_bb = ag->current_basic_block; return special_instruction; } template -static T *ir_build_instruction(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { - T *special_instruction = ir_create_instruction(irb, scope, source_node); - ir_instruction_append(irb->current_basic_block, &special_instruction->base); +static T *ir_build_instruction(Stage1AstGen *ag, Scope *scope, AstNode *source_node) { + T *special_instruction = ir_create_instruction(ag, scope, source_node); + ir_instruction_append(ag->current_basic_block, &special_instruction->base); return special_instruction; } -static IrInstSrc *ir_build_cond_br(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *condition, +static IrInstSrc *ir_build_cond_br(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *condition, IrBasicBlockSrc *then_block, IrBasicBlockSrc *else_block, IrInstSrc *is_comptime) { - IrInstSrcCondBr *inst = ir_build_instruction(irb, scope, source_node); + IrInstSrcCondBr *inst = ir_build_instruction(ag, scope, source_node); inst->base.is_noreturn = true; inst->condition = condition; inst->then_block = then_block; inst->else_block = else_block; inst->is_comptime = is_comptime; - ir_ref_instruction(condition, irb->current_basic_block); + ir_ref_instruction(condition, ag->current_basic_block); ir_ref_bb(then_block); ir_ref_bb(else_block); - if (is_comptime != nullptr) ir_ref_instruction(is_comptime, irb->current_basic_block); + if (is_comptime != nullptr) ir_ref_instruction(is_comptime, ag->current_basic_block); return &inst->base; } -static IrInstSrc *ir_build_return_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *operand) { - IrInstSrcReturn *inst = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_return_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *operand) { + IrInstSrcReturn *inst = ir_build_instruction(ag, scope, source_node); inst->base.is_noreturn = true; inst->operand = operand; - if (operand != nullptr) ir_ref_instruction(operand, irb->current_basic_block); + if (operand != nullptr) ir_ref_instruction(operand, ag->current_basic_block); return &inst->base; } -static IrInstSrc *ir_build_const_void(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { - IrInstSrcConst *const_instruction = ir_create_instruction(irb, scope, source_node); - ir_instruction_append(irb->current_basic_block, &const_instruction->base); - const_instruction->value = irb->codegen->intern.for_void(); +static IrInstSrc *ir_build_const_void(Stage1AstGen *ag, Scope *scope, AstNode *source_node) { + IrInstSrcConst *const_instruction = ir_create_instruction(ag, scope, source_node); + ir_instruction_append(ag->current_basic_block, &const_instruction->base); + const_instruction->value = ag->codegen->intern.for_void(); return &const_instruction->base; } -static IrInstSrc *ir_build_const_undefined(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { - IrInstSrcConst *const_instruction = ir_create_instruction(irb, scope, source_node); - ir_instruction_append(irb->current_basic_block, &const_instruction->base); - const_instruction->value = irb->codegen->intern.for_undefined(); +static IrInstSrc *ir_build_const_undefined(Stage1AstGen *ag, Scope *scope, AstNode *source_node) { + IrInstSrcConst *const_instruction = ir_create_instruction(ag, scope, source_node); + ir_instruction_append(ag->current_basic_block, &const_instruction->base); + const_instruction->value = ag->codegen->intern.for_undefined(); const_instruction->value->special = ConstValSpecialUndef; return &const_instruction->base; } -static IrInstSrc *ir_build_const_uint(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, uint64_t value) { - IrInstSrcConst *const_instruction = ir_build_instruction(irb, scope, source_node); - const_instruction->value = irb->codegen->pass1_arena->create(); - const_instruction->value->type = irb->codegen->builtin_types.entry_num_lit_int; +static IrInstSrc *ir_build_const_uint(Stage1AstGen *ag, Scope *scope, AstNode *source_node, uint64_t value) { + IrInstSrcConst *const_instruction = ir_build_instruction(ag, scope, source_node); + const_instruction->value = ag->codegen->pass1_arena->create(); + const_instruction->value->type = ag->codegen->builtin_types.entry_num_lit_int; const_instruction->value->special = ConstValSpecialStatic; bigint_init_unsigned(&const_instruction->value->data.x_bigint, value); return &const_instruction->base; } -static IrInstSrc *ir_build_const_bigint(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_const_bigint(Stage1AstGen *ag, Scope *scope, AstNode *source_node, BigInt bigint) { - IrInstSrcConst *const_instruction = ir_build_instruction(irb, scope, source_node); - const_instruction->value = irb->codegen->pass1_arena->create(); - const_instruction->value->type = irb->codegen->builtin_types.entry_num_lit_int; + IrInstSrcConst *const_instruction = ir_build_instruction(ag, scope, source_node); + const_instruction->value = ag->codegen->pass1_arena->create(); + const_instruction->value->type = ag->codegen->builtin_types.entry_num_lit_int; const_instruction->value->special = ConstValSpecialStatic; const_instruction->value->data.x_bigint = bigint; return &const_instruction->base; } -static IrInstSrc *ir_build_const_bigfloat(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_const_bigfloat(Stage1AstGen *ag, Scope *scope, AstNode *source_node, BigFloat bigfloat) { - IrInstSrcConst *const_instruction = ir_build_instruction(irb, scope, source_node); - const_instruction->value = irb->codegen->pass1_arena->create(); - const_instruction->value->type = irb->codegen->builtin_types.entry_num_lit_float; + IrInstSrcConst *const_instruction = ir_build_instruction(ag, scope, source_node); + const_instruction->value = ag->codegen->pass1_arena->create(); + const_instruction->value->type = ag->codegen->builtin_types.entry_num_lit_float; const_instruction->value->special = ConstValSpecialStatic; const_instruction->value->data.x_bigfloat = bigfloat; return &const_instruction->base; } -static IrInstSrc *ir_build_const_null(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { - IrInstSrcConst *const_instruction = ir_create_instruction(irb, scope, source_node); - ir_instruction_append(irb->current_basic_block, &const_instruction->base); - const_instruction->value = irb->codegen->intern.for_null(); +static IrInstSrc *ir_build_const_null(Stage1AstGen *ag, Scope *scope, AstNode *source_node) { + IrInstSrcConst *const_instruction = ir_create_instruction(ag, scope, source_node); + ir_instruction_append(ag->current_basic_block, &const_instruction->base); + const_instruction->value = ag->codegen->intern.for_null(); return &const_instruction->base; } -static IrInstSrc *ir_build_const_usize(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, uint64_t value) { - IrInstSrcConst *const_instruction = ir_build_instruction(irb, scope, source_node); - const_instruction->value = irb->codegen->pass1_arena->create(); - const_instruction->value->type = irb->codegen->builtin_types.entry_usize; +static IrInstSrc *ir_build_const_usize(Stage1AstGen *ag, Scope *scope, AstNode *source_node, uint64_t value) { + IrInstSrcConst *const_instruction = ir_build_instruction(ag, scope, source_node); + const_instruction->value = ag->codegen->pass1_arena->create(); + const_instruction->value->type = ag->codegen->builtin_types.entry_usize; const_instruction->value->special = ConstValSpecialStatic; bigint_init_unsigned(&const_instruction->value->data.x_bigint, value); return &const_instruction->base; } -static IrInstSrc *ir_create_const_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_create_const_type(Stage1AstGen *ag, Scope *scope, AstNode *source_node, ZigType *type_entry) { - IrInstSrcConst *const_instruction = ir_create_instruction(irb, scope, source_node); - const_instruction->value = irb->codegen->pass1_arena->create(); - const_instruction->value->type = irb->codegen->builtin_types.entry_type; + IrInstSrcConst *const_instruction = ir_create_instruction(ag, scope, source_node); + const_instruction->value = ag->codegen->pass1_arena->create(); + const_instruction->value->type = ag->codegen->builtin_types.entry_type; const_instruction->value->special = ConstValSpecialStatic; const_instruction->value->data.x_type = type_entry; return &const_instruction->base; } -static IrInstSrc *ir_build_const_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_const_type(Stage1AstGen *ag, Scope *scope, AstNode *source_node, ZigType *type_entry) { - IrInstSrc *instruction = ir_create_const_type(irb, scope, source_node, type_entry); - ir_instruction_append(irb->current_basic_block, instruction); + IrInstSrc *instruction = ir_create_const_type(ag, scope, source_node, type_entry); + ir_instruction_append(ag->current_basic_block, instruction); return instruction; } -static IrInstSrc *ir_build_const_import(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, ZigType *import) { - IrInstSrcConst *const_instruction = ir_build_instruction(irb, scope, source_node); - const_instruction->value = irb->codegen->pass1_arena->create(); - const_instruction->value->type = irb->codegen->builtin_types.entry_type; +static IrInstSrc *ir_build_const_import(Stage1AstGen *ag, Scope *scope, AstNode *source_node, ZigType *import) { + IrInstSrcConst *const_instruction = ir_build_instruction(ag, scope, source_node); + const_instruction->value = ag->codegen->pass1_arena->create(); + const_instruction->value->type = ag->codegen->builtin_types.entry_type; const_instruction->value->special = ConstValSpecialStatic; const_instruction->value->data.x_type = import; return &const_instruction->base; } -static IrInstSrc *ir_build_const_bool(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, bool value) { - IrInstSrcConst *const_instruction = ir_build_instruction(irb, scope, source_node); - const_instruction->value = irb->codegen->pass1_arena->create(); - const_instruction->value->type = irb->codegen->builtin_types.entry_bool; +static IrInstSrc *ir_build_const_bool(Stage1AstGen *ag, Scope *scope, AstNode *source_node, bool value) { + IrInstSrcConst *const_instruction = ir_build_instruction(ag, scope, source_node); + const_instruction->value = ag->codegen->pass1_arena->create(); + const_instruction->value->type = ag->codegen->builtin_types.entry_bool; const_instruction->value->special = ConstValSpecialStatic; const_instruction->value->data.x_bool = value; return &const_instruction->base; } -static IrInstSrc *ir_build_const_enum_literal(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, Buf *name) { - IrInstSrcConst *const_instruction = ir_build_instruction(irb, scope, source_node); - const_instruction->value = irb->codegen->pass1_arena->create(); - const_instruction->value->type = irb->codegen->builtin_types.entry_enum_literal; +static IrInstSrc *ir_build_const_enum_literal(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Buf *name) { + IrInstSrcConst *const_instruction = ir_build_instruction(ag, scope, source_node); + const_instruction->value = ag->codegen->pass1_arena->create(); + const_instruction->value->type = ag->codegen->builtin_types.entry_enum_literal; const_instruction->value->special = ConstValSpecialStatic; const_instruction->value->data.x_enum_literal = name; return &const_instruction->base; } // Consumes `str`. -static IrInstSrc *ir_create_const_str_lit(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, Buf *str) { - IrInstSrcConst *const_instruction = ir_create_instruction(irb, scope, source_node); - const_instruction->value = irb->codegen->pass1_arena->create(); - init_const_str_lit(irb->codegen, const_instruction->value, str, true); +static IrInstSrc *ir_create_const_str_lit(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Buf *str) { + IrInstSrcConst *const_instruction = ir_create_instruction(ag, scope, source_node); + const_instruction->value = ag->codegen->pass1_arena->create(); + init_const_str_lit(ag->codegen, const_instruction->value, str, true); return &const_instruction->base; } // Consumes `str`. -static IrInstSrc *ir_build_const_str_lit(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, Buf *str) { - IrInstSrc *instruction = ir_create_const_str_lit(irb, scope, source_node, str); - ir_instruction_append(irb->current_basic_block, instruction); +static IrInstSrc *ir_build_const_str_lit(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Buf *str) { + IrInstSrc *instruction = ir_create_const_str_lit(ag, scope, source_node, str); + ir_instruction_append(ag->current_basic_block, instruction); return instruction; } -static IrInstSrc *ir_build_bin_op(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrBinOp op_id, +static IrInstSrc *ir_build_bin_op(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrBinOp op_id, IrInstSrc *op1, IrInstSrc *op2, bool safety_check_on) { - IrInstSrcBinOp *inst = ir_build_instruction(irb, scope, source_node); + IrInstSrcBinOp *inst = ir_build_instruction(ag, scope, source_node); inst->op_id = op_id; inst->op1 = op1; inst->op2 = op2; inst->safety_check_on = safety_check_on; - ir_ref_instruction(op1, irb->current_basic_block); - ir_ref_instruction(op2, irb->current_basic_block); + ir_ref_instruction(op1, ag->current_basic_block); + ir_ref_instruction(op2, ag->current_basic_block); return &inst->base; } -static IrInstSrc *ir_build_merge_err_sets(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_merge_err_sets(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *op1, IrInstSrc *op2, Buf *type_name) { - IrInstSrcMergeErrSets *inst = ir_build_instruction(irb, scope, source_node); + IrInstSrcMergeErrSets *inst = ir_build_instruction(ag, scope, source_node); inst->op1 = op1; inst->op2 = op2; inst->type_name = type_name; - ir_ref_instruction(op1, irb->current_basic_block); - ir_ref_instruction(op2, irb->current_basic_block); + ir_ref_instruction(op1, ag->current_basic_block); + ir_ref_instruction(op2, ag->current_basic_block); return &inst->base; } -static IrInstSrc *ir_build_var_ptr_x(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, ZigVar *var, +static IrInstSrc *ir_build_var_ptr_x(Stage1AstGen *ag, Scope *scope, AstNode *source_node, ZigVar *var, ScopeFnDef *crossed_fndef_scope) { - IrInstSrcVarPtr *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcVarPtr *instruction = ir_build_instruction(ag, scope, source_node); instruction->var = var; instruction->crossed_fndef_scope = crossed_fndef_scope; @@ -1142,89 +1142,89 @@ static IrInstSrc *ir_build_var_ptr_x(IrBuilderSrc *irb, Scope *scope, AstNode *s return &instruction->base; } -static IrInstSrc *ir_build_var_ptr(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, ZigVar *var) { - return ir_build_var_ptr_x(irb, scope, source_node, var, nullptr); +static IrInstSrc *ir_build_var_ptr(Stage1AstGen *ag, Scope *scope, AstNode *source_node, ZigVar *var) { + return ir_build_var_ptr_x(ag, scope, source_node, var, nullptr); } -static IrInstSrc *ir_build_elem_ptr(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_elem_ptr(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *array_ptr, IrInstSrc *elem_index, bool safety_check_on, PtrLen ptr_len, AstNode *init_array_type_source_node) { - IrInstSrcElemPtr *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcElemPtr *instruction = ir_build_instruction(ag, scope, source_node); instruction->array_ptr = array_ptr; instruction->elem_index = elem_index; instruction->safety_check_on = safety_check_on; instruction->ptr_len = ptr_len; instruction->init_array_type_source_node = init_array_type_source_node; - ir_ref_instruction(array_ptr, irb->current_basic_block); - ir_ref_instruction(elem_index, irb->current_basic_block); + ir_ref_instruction(array_ptr, ag->current_basic_block); + ir_ref_instruction(elem_index, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_field_ptr_instruction(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_field_ptr_instruction(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *container_ptr, IrInstSrc *field_name_expr, bool initializing) { - IrInstSrcFieldPtr *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcFieldPtr *instruction = ir_build_instruction(ag, scope, source_node); instruction->container_ptr = container_ptr; instruction->field_name_buffer = nullptr; instruction->field_name_expr = field_name_expr; instruction->initializing = initializing; - ir_ref_instruction(container_ptr, irb->current_basic_block); - ir_ref_instruction(field_name_expr, irb->current_basic_block); + ir_ref_instruction(container_ptr, ag->current_basic_block); + ir_ref_instruction(field_name_expr, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_field_ptr(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_field_ptr(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *container_ptr, Buf *field_name, bool initializing) { - IrInstSrcFieldPtr *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcFieldPtr *instruction = ir_build_instruction(ag, scope, source_node); instruction->container_ptr = container_ptr; instruction->field_name_buffer = field_name; instruction->field_name_expr = nullptr; instruction->initializing = initializing; - ir_ref_instruction(container_ptr, irb->current_basic_block); + ir_ref_instruction(container_ptr, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_has_field(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_has_field(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *container_type, IrInstSrc *field_name) { - IrInstSrcHasField *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcHasField *instruction = ir_build_instruction(ag, scope, source_node); instruction->container_type = container_type; instruction->field_name = field_name; - ir_ref_instruction(container_type, irb->current_basic_block); - ir_ref_instruction(field_name, irb->current_basic_block); + ir_ref_instruction(container_type, ag->current_basic_block); + ir_ref_instruction(field_name, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_call_extra(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_call_extra(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *options, IrInstSrc *fn_ref, IrInstSrc *args, ResultLoc *result_loc) { - IrInstSrcCallExtra *call_instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcCallExtra *call_instruction = ir_build_instruction(ag, scope, source_node); call_instruction->options = options; call_instruction->fn_ref = fn_ref; call_instruction->args = args; call_instruction->result_loc = result_loc; - ir_ref_instruction(options, irb->current_basic_block); - ir_ref_instruction(fn_ref, irb->current_basic_block); - ir_ref_instruction(args, irb->current_basic_block); + ir_ref_instruction(options, ag->current_basic_block); + ir_ref_instruction(fn_ref, ag->current_basic_block); + ir_ref_instruction(args, ag->current_basic_block); return &call_instruction->base; } -static IrInstSrc *ir_build_async_call_extra(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_async_call_extra(Stage1AstGen *ag, Scope *scope, AstNode *source_node, CallModifier modifier, IrInstSrc *fn_ref, IrInstSrc *ret_ptr, IrInstSrc *new_stack, IrInstSrc *args, ResultLoc *result_loc) { - IrInstSrcAsyncCallExtra *call_instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcAsyncCallExtra *call_instruction = ir_build_instruction(ag, scope, source_node); call_instruction->modifier = modifier; call_instruction->fn_ref = fn_ref; call_instruction->ret_ptr = ret_ptr; @@ -1232,39 +1232,39 @@ static IrInstSrc *ir_build_async_call_extra(IrBuilderSrc *irb, Scope *scope, Ast call_instruction->args = args; call_instruction->result_loc = result_loc; - ir_ref_instruction(fn_ref, irb->current_basic_block); - if (ret_ptr != nullptr) ir_ref_instruction(ret_ptr, irb->current_basic_block); - ir_ref_instruction(new_stack, irb->current_basic_block); - ir_ref_instruction(args, irb->current_basic_block); + ir_ref_instruction(fn_ref, ag->current_basic_block); + if (ret_ptr != nullptr) ir_ref_instruction(ret_ptr, ag->current_basic_block); + ir_ref_instruction(new_stack, ag->current_basic_block); + ir_ref_instruction(args, ag->current_basic_block); return &call_instruction->base; } -static IrInstSrc *ir_build_call_args(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_call_args(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *options, IrInstSrc *fn_ref, IrInstSrc **args_ptr, size_t args_len, ResultLoc *result_loc) { - IrInstSrcCallArgs *call_instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcCallArgs *call_instruction = ir_build_instruction(ag, scope, source_node); call_instruction->options = options; call_instruction->fn_ref = fn_ref; call_instruction->args_ptr = args_ptr; call_instruction->args_len = args_len; call_instruction->result_loc = result_loc; - ir_ref_instruction(options, irb->current_basic_block); - ir_ref_instruction(fn_ref, irb->current_basic_block); + ir_ref_instruction(options, ag->current_basic_block); + ir_ref_instruction(fn_ref, ag->current_basic_block); for (size_t i = 0; i < args_len; i += 1) - ir_ref_instruction(args_ptr[i], irb->current_basic_block); + ir_ref_instruction(args_ptr[i], ag->current_basic_block); return &call_instruction->base; } -static IrInstSrc *ir_build_call_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_call_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, ZigFn *fn_entry, IrInstSrc *fn_ref, size_t arg_count, IrInstSrc **args, IrInstSrc *ret_ptr, CallModifier modifier, bool is_async_call_builtin, IrInstSrc *new_stack, ResultLoc *result_loc) { - IrInstSrcCall *call_instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcCall *call_instruction = ir_build_instruction(ag, scope, source_node); call_instruction->fn_entry = fn_entry; call_instruction->fn_ref = fn_ref; call_instruction->args = args; @@ -1275,23 +1275,23 @@ static IrInstSrc *ir_build_call_src(IrBuilderSrc *irb, Scope *scope, AstNode *so call_instruction->result_loc = result_loc; call_instruction->ret_ptr = ret_ptr; - if (fn_ref != nullptr) ir_ref_instruction(fn_ref, irb->current_basic_block); + if (fn_ref != nullptr) ir_ref_instruction(fn_ref, ag->current_basic_block); for (size_t i = 0; i < arg_count; i += 1) - ir_ref_instruction(args[i], irb->current_basic_block); - if (ret_ptr != nullptr) ir_ref_instruction(ret_ptr, irb->current_basic_block); - if (new_stack != nullptr) ir_ref_instruction(new_stack, irb->current_basic_block); + ir_ref_instruction(args[i], ag->current_basic_block); + if (ret_ptr != nullptr) ir_ref_instruction(ret_ptr, ag->current_basic_block); + if (new_stack != nullptr) ir_ref_instruction(new_stack, ag->current_basic_block); return &call_instruction->base; } -static IrInstSrc *ir_build_phi(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_phi(Stage1AstGen *ag, Scope *scope, AstNode *source_node, size_t incoming_count, IrBasicBlockSrc **incoming_blocks, IrInstSrc **incoming_values, ResultLocPeerParent *peer_parent) { assert(incoming_count != 0); assert(incoming_count != SIZE_MAX); - IrInstSrcPhi *phi_instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcPhi *phi_instruction = ir_build_instruction(ag, scope, source_node); phi_instruction->incoming_count = incoming_count; phi_instruction->incoming_blocks = incoming_blocks; phi_instruction->incoming_values = incoming_values; @@ -1299,45 +1299,45 @@ static IrInstSrc *ir_build_phi(IrBuilderSrc *irb, Scope *scope, AstNode *source_ for (size_t i = 0; i < incoming_count; i += 1) { ir_ref_bb(incoming_blocks[i]); - ir_ref_instruction(incoming_values[i], irb->current_basic_block); + ir_ref_instruction(incoming_values[i], ag->current_basic_block); } return &phi_instruction->base; } -static IrInstSrc *ir_build_br(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_br(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrBasicBlockSrc *dest_block, IrInstSrc *is_comptime) { - IrInstSrcBr *inst = ir_build_instruction(irb, scope, source_node); + IrInstSrcBr *inst = ir_build_instruction(ag, scope, source_node); inst->base.is_noreturn = true; inst->dest_block = dest_block; inst->is_comptime = is_comptime; ir_ref_bb(dest_block); - if (is_comptime) ir_ref_instruction(is_comptime, irb->current_basic_block); + if (is_comptime) ir_ref_instruction(is_comptime, ag->current_basic_block); return &inst->base; } -static IrInstSrc *ir_build_ptr_type_simple(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_ptr_type_simple(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *child_type, bool is_const) { IrInstSrcPtrTypeSimple *inst = heap::c_allocator.create(); inst->base.id = is_const ? IrInstSrcIdPtrTypeSimpleConst : IrInstSrcIdPtrTypeSimple; inst->base.base.scope = scope; inst->base.base.source_node = source_node; - inst->base.base.debug_id = irb_next_debug_id(irb); - inst->base.owner_bb = irb->current_basic_block; - ir_instruction_append(irb->current_basic_block, &inst->base); + inst->base.base.debug_id = irb_next_debug_id(ag); + inst->base.owner_bb = ag->current_basic_block; + ir_instruction_append(ag->current_basic_block, &inst->base); inst->child_type = child_type; - ir_ref_instruction(child_type, irb->current_basic_block); + ir_ref_instruction(child_type, ag->current_basic_block); return &inst->base; } -static IrInstSrc *ir_build_ptr_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_ptr_type(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *child_type, bool is_const, bool is_volatile, PtrLen ptr_len, IrInstSrc *sentinel, IrInstSrc *align_value, uint32_t bit_offset_start, uint32_t host_int_bytes, bool is_allow_zero) @@ -1345,10 +1345,10 @@ static IrInstSrc *ir_build_ptr_type(IrBuilderSrc *irb, Scope *scope, AstNode *so if (!is_volatile && ptr_len == PtrLenSingle && sentinel == nullptr && align_value == nullptr && bit_offset_start == 0 && host_int_bytes == 0 && is_allow_zero == 0) { - return ir_build_ptr_type_simple(irb, scope, source_node, child_type, is_const); + return ir_build_ptr_type_simple(ag, scope, source_node, child_type, is_const); } - IrInstSrcPtrType *inst = ir_build_instruction(irb, scope, source_node); + IrInstSrcPtrType *inst = ir_build_instruction(ag, scope, source_node); inst->sentinel = sentinel; inst->align_value = align_value; inst->child_type = child_type; @@ -1359,225 +1359,225 @@ static IrInstSrc *ir_build_ptr_type(IrBuilderSrc *irb, Scope *scope, AstNode *so inst->host_int_bytes = host_int_bytes; inst->is_allow_zero = is_allow_zero; - if (sentinel) ir_ref_instruction(sentinel, irb->current_basic_block); - if (align_value) ir_ref_instruction(align_value, irb->current_basic_block); - ir_ref_instruction(child_type, irb->current_basic_block); + if (sentinel) ir_ref_instruction(sentinel, ag->current_basic_block); + if (align_value) ir_ref_instruction(align_value, ag->current_basic_block); + ir_ref_instruction(child_type, ag->current_basic_block); return &inst->base; } -static IrInstSrc *ir_build_un_op_lval(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrUnOp op_id, +static IrInstSrc *ir_build_un_op_lval(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrUnOp op_id, IrInstSrc *value, LVal lval, ResultLoc *result_loc) { - IrInstSrcUnOp *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcUnOp *instruction = ir_build_instruction(ag, scope, source_node); instruction->op_id = op_id; instruction->value = value; instruction->lval = lval; instruction->result_loc = result_loc; - ir_ref_instruction(value, irb->current_basic_block); + ir_ref_instruction(value, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_un_op(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrUnOp op_id, +static IrInstSrc *ir_build_un_op(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrUnOp op_id, IrInstSrc *value) { - return ir_build_un_op_lval(irb, scope, source_node, op_id, value, LValNone, nullptr); + return ir_build_un_op_lval(ag, scope, source_node, op_id, value, LValNone, nullptr); } -static IrInstSrc *ir_build_container_init_list(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_container_init_list(Stage1AstGen *ag, Scope *scope, AstNode *source_node, size_t item_count, IrInstSrc **elem_result_loc_list, IrInstSrc *result_loc, AstNode *init_array_type_source_node) { IrInstSrcContainerInitList *container_init_list_instruction = - ir_build_instruction(irb, scope, source_node); + ir_build_instruction(ag, scope, source_node); container_init_list_instruction->item_count = item_count; container_init_list_instruction->elem_result_loc_list = elem_result_loc_list; container_init_list_instruction->result_loc = result_loc; container_init_list_instruction->init_array_type_source_node = init_array_type_source_node; for (size_t i = 0; i < item_count; i += 1) { - ir_ref_instruction(elem_result_loc_list[i], irb->current_basic_block); + ir_ref_instruction(elem_result_loc_list[i], ag->current_basic_block); } - if (result_loc != nullptr) ir_ref_instruction(result_loc, irb->current_basic_block); + if (result_loc != nullptr) ir_ref_instruction(result_loc, ag->current_basic_block); return &container_init_list_instruction->base; } -static IrInstSrc *ir_build_container_init_fields(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_container_init_fields(Stage1AstGen *ag, Scope *scope, AstNode *source_node, size_t field_count, IrInstSrcContainerInitFieldsField *fields, IrInstSrc *result_loc) { IrInstSrcContainerInitFields *container_init_fields_instruction = - ir_build_instruction(irb, scope, source_node); + ir_build_instruction(ag, scope, source_node); container_init_fields_instruction->field_count = field_count; container_init_fields_instruction->fields = fields; container_init_fields_instruction->result_loc = result_loc; for (size_t i = 0; i < field_count; i += 1) { - ir_ref_instruction(fields[i].result_loc, irb->current_basic_block); + ir_ref_instruction(fields[i].result_loc, ag->current_basic_block); } - if (result_loc != nullptr) ir_ref_instruction(result_loc, irb->current_basic_block); + if (result_loc != nullptr) ir_ref_instruction(result_loc, ag->current_basic_block); return &container_init_fields_instruction->base; } -static IrInstSrc *ir_build_unreachable(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { - IrInstSrcUnreachable *inst = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_unreachable(Stage1AstGen *ag, Scope *scope, AstNode *source_node) { + IrInstSrcUnreachable *inst = ir_build_instruction(ag, scope, source_node); inst->base.is_noreturn = true; return &inst->base; } -static IrInstSrcStorePtr *ir_build_store_ptr(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrcStorePtr *ir_build_store_ptr(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *ptr, IrInstSrc *value) { - IrInstSrcStorePtr *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcStorePtr *instruction = ir_build_instruction(ag, scope, source_node); instruction->ptr = ptr; instruction->value = value; - ir_ref_instruction(ptr, irb->current_basic_block); - ir_ref_instruction(value, irb->current_basic_block); + ir_ref_instruction(ptr, ag->current_basic_block); + ir_ref_instruction(value, ag->current_basic_block); return instruction; } -static IrInstSrc *ir_build_var_decl_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_var_decl_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, ZigVar *var, IrInstSrc *align_value, IrInstSrc *ptr) { - IrInstSrcDeclVar *inst = ir_build_instruction(irb, scope, source_node); + IrInstSrcDeclVar *inst = ir_build_instruction(ag, scope, source_node); inst->var = var; inst->align_value = align_value; inst->ptr = ptr; - if (align_value != nullptr) ir_ref_instruction(align_value, irb->current_basic_block); - ir_ref_instruction(ptr, irb->current_basic_block); + if (align_value != nullptr) ir_ref_instruction(align_value, ag->current_basic_block); + ir_ref_instruction(ptr, ag->current_basic_block); return &inst->base; } -static IrInstSrc *ir_build_export(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_export(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *target, IrInstSrc *options) { IrInstSrcExport *export_instruction = ir_build_instruction( - irb, scope, source_node); + ag, scope, source_node); export_instruction->target = target; export_instruction->options = options; - ir_ref_instruction(target, irb->current_basic_block); - ir_ref_instruction(options, irb->current_basic_block); + ir_ref_instruction(target, ag->current_basic_block); + ir_ref_instruction(options, ag->current_basic_block); return &export_instruction->base; } -static IrInstSrc *ir_build_extern(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_extern(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *type, IrInstSrc *options) { IrInstSrcExtern *extern_instruction = ir_build_instruction( - irb, scope, source_node); + ag, scope, source_node); extern_instruction->type = type; extern_instruction->options = options; - ir_ref_instruction(type, irb->current_basic_block); - ir_ref_instruction(options, irb->current_basic_block); + ir_ref_instruction(type, ag->current_basic_block); + ir_ref_instruction(options, ag->current_basic_block); return &extern_instruction->base; } -static IrInstSrc *ir_build_load_ptr(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *ptr) { - IrInstSrcLoadPtr *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_load_ptr(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *ptr) { + IrInstSrcLoadPtr *instruction = ir_build_instruction(ag, scope, source_node); instruction->ptr = ptr; - ir_ref_instruction(ptr, irb->current_basic_block); + ir_ref_instruction(ptr, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_typeof_n(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_typeof_n(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc **values, size_t value_count) { assert(value_count >= 2); - IrInstSrcTypeOf *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcTypeOf *instruction = ir_build_instruction(ag, scope, source_node); instruction->value.list = values; instruction->value_count = value_count; for (size_t i = 0; i < value_count; i++) - ir_ref_instruction(values[i], irb->current_basic_block); + ir_ref_instruction(values[i], ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_typeof_1(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *value) { - IrInstSrcTypeOf *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_typeof_1(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *value) { + IrInstSrcTypeOf *instruction = ir_build_instruction(ag, scope, source_node); instruction->value.scalar = value; - ir_ref_instruction(value, irb->current_basic_block); + ir_ref_instruction(value, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_set_cold(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *is_cold) { - IrInstSrcSetCold *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_set_cold(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *is_cold) { + IrInstSrcSetCold *instruction = ir_build_instruction(ag, scope, source_node); instruction->is_cold = is_cold; - ir_ref_instruction(is_cold, irb->current_basic_block); + ir_ref_instruction(is_cold, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_set_runtime_safety(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_set_runtime_safety(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *safety_on) { - IrInstSrcSetRuntimeSafety *inst = ir_build_instruction(irb, scope, source_node); + IrInstSrcSetRuntimeSafety *inst = ir_build_instruction(ag, scope, source_node); inst->safety_on = safety_on; - ir_ref_instruction(safety_on, irb->current_basic_block); + ir_ref_instruction(safety_on, ag->current_basic_block); return &inst->base; } -static IrInstSrc *ir_build_set_float_mode(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_set_float_mode(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *mode_value) { - IrInstSrcSetFloatMode *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcSetFloatMode *instruction = ir_build_instruction(ag, scope, source_node); instruction->mode_value = mode_value; - ir_ref_instruction(mode_value, irb->current_basic_block); + ir_ref_instruction(mode_value, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_array_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *size, +static IrInstSrc *ir_build_array_type(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *size, IrInstSrc *sentinel, IrInstSrc *child_type) { - IrInstSrcArrayType *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcArrayType *instruction = ir_build_instruction(ag, scope, source_node); instruction->size = size; instruction->sentinel = sentinel; instruction->child_type = child_type; - ir_ref_instruction(size, irb->current_basic_block); - if (sentinel != nullptr) ir_ref_instruction(sentinel, irb->current_basic_block); - ir_ref_instruction(child_type, irb->current_basic_block); + ir_ref_instruction(size, ag->current_basic_block); + if (sentinel != nullptr) ir_ref_instruction(sentinel, ag->current_basic_block); + ir_ref_instruction(child_type, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_anyframe_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_anyframe_type(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *payload_type) { - IrInstSrcAnyFrameType *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcAnyFrameType *instruction = ir_build_instruction(ag, scope, source_node); instruction->payload_type = payload_type; - if (payload_type != nullptr) ir_ref_instruction(payload_type, irb->current_basic_block); + if (payload_type != nullptr) ir_ref_instruction(payload_type, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_slice_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_slice_type(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *child_type, bool is_const, bool is_volatile, IrInstSrc *sentinel, IrInstSrc *align_value, bool is_allow_zero) { - IrInstSrcSliceType *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcSliceType *instruction = ir_build_instruction(ag, scope, source_node); instruction->is_const = is_const; instruction->is_volatile = is_volatile; instruction->child_type = child_type; @@ -1585,18 +1585,18 @@ static IrInstSrc *ir_build_slice_type(IrBuilderSrc *irb, Scope *scope, AstNode * instruction->align_value = align_value; instruction->is_allow_zero = is_allow_zero; - if (sentinel != nullptr) ir_ref_instruction(sentinel, irb->current_basic_block); - if (align_value != nullptr) ir_ref_instruction(align_value, irb->current_basic_block); - ir_ref_instruction(child_type, irb->current_basic_block); + if (sentinel != nullptr) ir_ref_instruction(sentinel, ag->current_basic_block); + if (align_value != nullptr) ir_ref_instruction(align_value, ag->current_basic_block); + ir_ref_instruction(child_type, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_asm_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_asm_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *asm_template, IrInstSrc **input_list, IrInstSrc **output_types, ZigVar **output_vars, size_t return_count, bool has_side_effects, bool is_global) { - IrInstSrcAsm *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcAsm *instruction = ir_build_instruction(ag, scope, source_node); instruction->asm_template = asm_template; instruction->input_list = input_list; instruction->output_types = output_types; @@ -1608,122 +1608,122 @@ static IrInstSrc *ir_build_asm_src(IrBuilderSrc *irb, Scope *scope, AstNode *sou assert(source_node->type == NodeTypeAsmExpr); for (size_t i = 0; i < source_node->data.asm_expr.output_list.length; i += 1) { IrInstSrc *output_type = output_types[i]; - if (output_type) ir_ref_instruction(output_type, irb->current_basic_block); + if (output_type) ir_ref_instruction(output_type, ag->current_basic_block); } for (size_t i = 0; i < source_node->data.asm_expr.input_list.length; i += 1) { IrInstSrc *input_value = input_list[i]; - ir_ref_instruction(input_value, irb->current_basic_block); + ir_ref_instruction(input_value, ag->current_basic_block); } return &instruction->base; } -static IrInstSrc *ir_build_size_of(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *type_value, +static IrInstSrc *ir_build_size_of(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *type_value, bool bit_size) { - IrInstSrcSizeOf *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcSizeOf *instruction = ir_build_instruction(ag, scope, source_node); instruction->type_value = type_value; instruction->bit_size = bit_size; - ir_ref_instruction(type_value, irb->current_basic_block); + ir_ref_instruction(type_value, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_test_non_null_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_test_non_null_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *value) { - IrInstSrcTestNonNull *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcTestNonNull *instruction = ir_build_instruction(ag, scope, source_node); instruction->value = value; - ir_ref_instruction(value, irb->current_basic_block); + ir_ref_instruction(value, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_optional_unwrap_ptr(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_optional_unwrap_ptr(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *base_ptr, bool safety_check_on) { - IrInstSrcOptionalUnwrapPtr *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcOptionalUnwrapPtr *instruction = ir_build_instruction(ag, scope, source_node); instruction->base_ptr = base_ptr; instruction->safety_check_on = safety_check_on; - ir_ref_instruction(base_ptr, irb->current_basic_block); + ir_ref_instruction(base_ptr, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_clz(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *type, +static IrInstSrc *ir_build_clz(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *type, IrInstSrc *op) { - IrInstSrcClz *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcClz *instruction = ir_build_instruction(ag, scope, source_node); instruction->type = type; instruction->op = op; - ir_ref_instruction(type, irb->current_basic_block); - ir_ref_instruction(op, irb->current_basic_block); + ir_ref_instruction(type, ag->current_basic_block); + ir_ref_instruction(op, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_ctz(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *type, +static IrInstSrc *ir_build_ctz(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *type, IrInstSrc *op) { - IrInstSrcCtz *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcCtz *instruction = ir_build_instruction(ag, scope, source_node); instruction->type = type; instruction->op = op; - ir_ref_instruction(type, irb->current_basic_block); - ir_ref_instruction(op, irb->current_basic_block); + ir_ref_instruction(type, ag->current_basic_block); + ir_ref_instruction(op, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_pop_count(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *type, +static IrInstSrc *ir_build_pop_count(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *type, IrInstSrc *op) { - IrInstSrcPopCount *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcPopCount *instruction = ir_build_instruction(ag, scope, source_node); instruction->type = type; instruction->op = op; - ir_ref_instruction(type, irb->current_basic_block); - ir_ref_instruction(op, irb->current_basic_block); + ir_ref_instruction(type, ag->current_basic_block); + ir_ref_instruction(op, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_bswap(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *type, +static IrInstSrc *ir_build_bswap(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *type, IrInstSrc *op) { - IrInstSrcBswap *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcBswap *instruction = ir_build_instruction(ag, scope, source_node); instruction->type = type; instruction->op = op; - ir_ref_instruction(type, irb->current_basic_block); - ir_ref_instruction(op, irb->current_basic_block); + ir_ref_instruction(type, ag->current_basic_block); + ir_ref_instruction(op, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_bit_reverse(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *type, +static IrInstSrc *ir_build_bit_reverse(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *type, IrInstSrc *op) { - IrInstSrcBitReverse *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcBitReverse *instruction = ir_build_instruction(ag, scope, source_node); instruction->type = type; instruction->op = op; - ir_ref_instruction(type, irb->current_basic_block); - ir_ref_instruction(op, irb->current_basic_block); + ir_ref_instruction(type, ag->current_basic_block); + ir_ref_instruction(op, ag->current_basic_block); return &instruction->base; } -static IrInstSrcSwitchBr *ir_build_switch_br_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrcSwitchBr *ir_build_switch_br_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *target_value, IrBasicBlockSrc *else_block, size_t case_count, IrInstSrcSwitchBrCase *cases, IrInstSrc *is_comptime, IrInstSrc *switch_prongs_void) { - IrInstSrcSwitchBr *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcSwitchBr *instruction = ir_build_instruction(ag, scope, source_node); instruction->base.is_noreturn = true; instruction->target_value = target_value; instruction->else_block = else_block; @@ -1732,156 +1732,156 @@ static IrInstSrcSwitchBr *ir_build_switch_br_src(IrBuilderSrc *irb, Scope *scope instruction->is_comptime = is_comptime; instruction->switch_prongs_void = switch_prongs_void; - ir_ref_instruction(target_value, irb->current_basic_block); - ir_ref_instruction(is_comptime, irb->current_basic_block); + ir_ref_instruction(target_value, ag->current_basic_block); + ir_ref_instruction(is_comptime, ag->current_basic_block); ir_ref_bb(else_block); - ir_ref_instruction(switch_prongs_void, irb->current_basic_block); + ir_ref_instruction(switch_prongs_void, ag->current_basic_block); for (size_t i = 0; i < case_count; i += 1) { - ir_ref_instruction(cases[i].value, irb->current_basic_block); + ir_ref_instruction(cases[i].value, ag->current_basic_block); ir_ref_bb(cases[i].block); } return instruction; } -static IrInstSrc *ir_build_switch_target(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_switch_target(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *target_value_ptr) { - IrInstSrcSwitchTarget *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcSwitchTarget *instruction = ir_build_instruction(ag, scope, source_node); instruction->target_value_ptr = target_value_ptr; - ir_ref_instruction(target_value_ptr, irb->current_basic_block); + ir_ref_instruction(target_value_ptr, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_switch_var(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_switch_var(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *target_value_ptr, IrInstSrc **prongs_ptr, size_t prongs_len) { - IrInstSrcSwitchVar *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcSwitchVar *instruction = ir_build_instruction(ag, scope, source_node); instruction->target_value_ptr = target_value_ptr; instruction->prongs_ptr = prongs_ptr; instruction->prongs_len = prongs_len; - ir_ref_instruction(target_value_ptr, irb->current_basic_block); + ir_ref_instruction(target_value_ptr, ag->current_basic_block); for (size_t i = 0; i < prongs_len; i += 1) { - ir_ref_instruction(prongs_ptr[i], irb->current_basic_block); + ir_ref_instruction(prongs_ptr[i], ag->current_basic_block); } return &instruction->base; } // For this instruction the switch_br must be set later. -static IrInstSrcSwitchElseVar *ir_build_switch_else_var(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrcSwitchElseVar *ir_build_switch_else_var(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *target_value_ptr) { - IrInstSrcSwitchElseVar *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcSwitchElseVar *instruction = ir_build_instruction(ag, scope, source_node); instruction->target_value_ptr = target_value_ptr; - ir_ref_instruction(target_value_ptr, irb->current_basic_block); + ir_ref_instruction(target_value_ptr, ag->current_basic_block); return instruction; } -static IrInstSrc *ir_build_import(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *name) { - IrInstSrcImport *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_import(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *name) { + IrInstSrcImport *instruction = ir_build_instruction(ag, scope, source_node); instruction->name = name; - ir_ref_instruction(name, irb->current_basic_block); + ir_ref_instruction(name, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_ref_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *value) { - IrInstSrcRef *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_ref_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *value) { + IrInstSrcRef *instruction = ir_build_instruction(ag, scope, source_node); instruction->value = value; - ir_ref_instruction(value, irb->current_basic_block); + ir_ref_instruction(value, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_compile_err(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *msg) { - IrInstSrcCompileErr *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_compile_err(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *msg) { + IrInstSrcCompileErr *instruction = ir_build_instruction(ag, scope, source_node); instruction->msg = msg; - ir_ref_instruction(msg, irb->current_basic_block); + ir_ref_instruction(msg, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_compile_log(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_compile_log(Stage1AstGen *ag, Scope *scope, AstNode *source_node, size_t msg_count, IrInstSrc **msg_list) { - IrInstSrcCompileLog *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcCompileLog *instruction = ir_build_instruction(ag, scope, source_node); instruction->msg_count = msg_count; instruction->msg_list = msg_list; for (size_t i = 0; i < msg_count; i += 1) { - ir_ref_instruction(msg_list[i], irb->current_basic_block); + ir_ref_instruction(msg_list[i], ag->current_basic_block); } return &instruction->base; } -static IrInstSrc *ir_build_err_name(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *value) { - IrInstSrcErrName *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_err_name(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *value) { + IrInstSrcErrName *instruction = ir_build_instruction(ag, scope, source_node); instruction->value = value; - ir_ref_instruction(value, irb->current_basic_block); + ir_ref_instruction(value, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_c_import(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { - IrInstSrcCImport *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_c_import(Stage1AstGen *ag, Scope *scope, AstNode *source_node) { + IrInstSrcCImport *instruction = ir_build_instruction(ag, scope, source_node); return &instruction->base; } -static IrInstSrc *ir_build_c_include(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *name) { - IrInstSrcCInclude *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_c_include(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *name) { + IrInstSrcCInclude *instruction = ir_build_instruction(ag, scope, source_node); instruction->name = name; - ir_ref_instruction(name, irb->current_basic_block); + ir_ref_instruction(name, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_c_define(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *name, IrInstSrc *value) { - IrInstSrcCDefine *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_c_define(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *name, IrInstSrc *value) { + IrInstSrcCDefine *instruction = ir_build_instruction(ag, scope, source_node); instruction->name = name; instruction->value = value; - ir_ref_instruction(name, irb->current_basic_block); - ir_ref_instruction(value, irb->current_basic_block); + ir_ref_instruction(name, ag->current_basic_block); + ir_ref_instruction(value, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_c_undef(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *name) { - IrInstSrcCUndef *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_c_undef(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *name) { + IrInstSrcCUndef *instruction = ir_build_instruction(ag, scope, source_node); instruction->name = name; - ir_ref_instruction(name, irb->current_basic_block); + ir_ref_instruction(name, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_embed_file(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *name) { - IrInstSrcEmbedFile *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_embed_file(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *name) { + IrInstSrcEmbedFile *instruction = ir_build_instruction(ag, scope, source_node); instruction->name = name; - ir_ref_instruction(name, irb->current_basic_block); + ir_ref_instruction(name, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_cmpxchg_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_cmpxchg_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *type_value, IrInstSrc *ptr, IrInstSrc *cmp_value, IrInstSrc *new_value, IrInstSrc *success_order_value, IrInstSrc *failure_order_value, bool is_weak, ResultLoc *result_loc) { - IrInstSrcCmpxchg *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcCmpxchg *instruction = ir_build_instruction(ag, scope, source_node); instruction->type_value = type_value; instruction->ptr = ptr; instruction->cmp_value = cmp_value; @@ -1891,210 +1891,210 @@ static IrInstSrc *ir_build_cmpxchg_src(IrBuilderSrc *irb, Scope *scope, AstNode instruction->is_weak = is_weak; instruction->result_loc = result_loc; - ir_ref_instruction(type_value, irb->current_basic_block); - ir_ref_instruction(ptr, irb->current_basic_block); - ir_ref_instruction(cmp_value, irb->current_basic_block); - ir_ref_instruction(new_value, irb->current_basic_block); - ir_ref_instruction(success_order_value, irb->current_basic_block); - ir_ref_instruction(failure_order_value, irb->current_basic_block); + ir_ref_instruction(type_value, ag->current_basic_block); + ir_ref_instruction(ptr, ag->current_basic_block); + ir_ref_instruction(cmp_value, ag->current_basic_block); + ir_ref_instruction(new_value, ag->current_basic_block); + ir_ref_instruction(success_order_value, ag->current_basic_block); + ir_ref_instruction(failure_order_value, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_fence(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *order) { - IrInstSrcFence *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_fence(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *order) { + IrInstSrcFence *instruction = ir_build_instruction(ag, scope, source_node); instruction->order = order; - ir_ref_instruction(order, irb->current_basic_block); + ir_ref_instruction(order, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_reduce(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *op, IrInstSrc *value) { - IrInstSrcReduce *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_reduce(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *op, IrInstSrc *value) { + IrInstSrcReduce *instruction = ir_build_instruction(ag, scope, source_node); instruction->op = op; instruction->value = value; - ir_ref_instruction(op, irb->current_basic_block); - ir_ref_instruction(value, irb->current_basic_block); + ir_ref_instruction(op, ag->current_basic_block); + ir_ref_instruction(value, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_truncate(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_truncate(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *dest_type, IrInstSrc *target) { - IrInstSrcTruncate *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcTruncate *instruction = ir_build_instruction(ag, scope, source_node); instruction->dest_type = dest_type; instruction->target = target; - ir_ref_instruction(dest_type, irb->current_basic_block); - ir_ref_instruction(target, irb->current_basic_block); + ir_ref_instruction(dest_type, ag->current_basic_block); + ir_ref_instruction(target, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_int_cast(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *dest_type, +static IrInstSrc *ir_build_int_cast(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *dest_type, IrInstSrc *target) { - IrInstSrcIntCast *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcIntCast *instruction = ir_build_instruction(ag, scope, source_node); instruction->dest_type = dest_type; instruction->target = target; - ir_ref_instruction(dest_type, irb->current_basic_block); - ir_ref_instruction(target, irb->current_basic_block); + ir_ref_instruction(dest_type, ag->current_basic_block); + ir_ref_instruction(target, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_float_cast(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *dest_type, +static IrInstSrc *ir_build_float_cast(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *dest_type, IrInstSrc *target) { - IrInstSrcFloatCast *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcFloatCast *instruction = ir_build_instruction(ag, scope, source_node); instruction->dest_type = dest_type; instruction->target = target; - ir_ref_instruction(dest_type, irb->current_basic_block); - ir_ref_instruction(target, irb->current_basic_block); + ir_ref_instruction(dest_type, ag->current_basic_block); + ir_ref_instruction(target, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_err_set_cast(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_err_set_cast(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *dest_type, IrInstSrc *target) { - IrInstSrcErrSetCast *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcErrSetCast *instruction = ir_build_instruction(ag, scope, source_node); instruction->dest_type = dest_type; instruction->target = target; - ir_ref_instruction(dest_type, irb->current_basic_block); - ir_ref_instruction(target, irb->current_basic_block); + ir_ref_instruction(dest_type, ag->current_basic_block); + ir_ref_instruction(target, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_int_to_float(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_int_to_float(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *dest_type, IrInstSrc *target) { - IrInstSrcIntToFloat *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcIntToFloat *instruction = ir_build_instruction(ag, scope, source_node); instruction->dest_type = dest_type; instruction->target = target; - ir_ref_instruction(dest_type, irb->current_basic_block); - ir_ref_instruction(target, irb->current_basic_block); + ir_ref_instruction(dest_type, ag->current_basic_block); + ir_ref_instruction(target, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_float_to_int(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_float_to_int(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *dest_type, IrInstSrc *target) { - IrInstSrcFloatToInt *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcFloatToInt *instruction = ir_build_instruction(ag, scope, source_node); instruction->dest_type = dest_type; instruction->target = target; - ir_ref_instruction(dest_type, irb->current_basic_block); - ir_ref_instruction(target, irb->current_basic_block); + ir_ref_instruction(dest_type, ag->current_basic_block); + ir_ref_instruction(target, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_bool_to_int(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *target) { - IrInstSrcBoolToInt *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_bool_to_int(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *target) { + IrInstSrcBoolToInt *instruction = ir_build_instruction(ag, scope, source_node); instruction->target = target; - ir_ref_instruction(target, irb->current_basic_block); + ir_ref_instruction(target, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_vector_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *len, +static IrInstSrc *ir_build_vector_type(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *len, IrInstSrc *elem_type) { - IrInstSrcVectorType *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcVectorType *instruction = ir_build_instruction(ag, scope, source_node); instruction->len = len; instruction->elem_type = elem_type; - ir_ref_instruction(len, irb->current_basic_block); - ir_ref_instruction(elem_type, irb->current_basic_block); + ir_ref_instruction(len, ag->current_basic_block); + ir_ref_instruction(elem_type, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_shuffle_vector(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_shuffle_vector(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *scalar_type, IrInstSrc *a, IrInstSrc *b, IrInstSrc *mask) { - IrInstSrcShuffleVector *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcShuffleVector *instruction = ir_build_instruction(ag, scope, source_node); instruction->scalar_type = scalar_type; instruction->a = a; instruction->b = b; instruction->mask = mask; - if (scalar_type != nullptr) ir_ref_instruction(scalar_type, irb->current_basic_block); - ir_ref_instruction(a, irb->current_basic_block); - ir_ref_instruction(b, irb->current_basic_block); - ir_ref_instruction(mask, irb->current_basic_block); + if (scalar_type != nullptr) ir_ref_instruction(scalar_type, ag->current_basic_block); + ir_ref_instruction(a, ag->current_basic_block); + ir_ref_instruction(b, ag->current_basic_block); + ir_ref_instruction(mask, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_splat_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_splat_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *len, IrInstSrc *scalar) { - IrInstSrcSplat *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcSplat *instruction = ir_build_instruction(ag, scope, source_node); instruction->len = len; instruction->scalar = scalar; - ir_ref_instruction(len, irb->current_basic_block); - ir_ref_instruction(scalar, irb->current_basic_block); + ir_ref_instruction(len, ag->current_basic_block); + ir_ref_instruction(scalar, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_bool_not(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *value) { - IrInstSrcBoolNot *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_bool_not(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *value) { + IrInstSrcBoolNot *instruction = ir_build_instruction(ag, scope, source_node); instruction->value = value; - ir_ref_instruction(value, irb->current_basic_block); + ir_ref_instruction(value, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_memset_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_memset_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *dest_ptr, IrInstSrc *byte, IrInstSrc *count) { - IrInstSrcMemset *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcMemset *instruction = ir_build_instruction(ag, scope, source_node); instruction->dest_ptr = dest_ptr; instruction->byte = byte; instruction->count = count; - ir_ref_instruction(dest_ptr, irb->current_basic_block); - ir_ref_instruction(byte, irb->current_basic_block); - ir_ref_instruction(count, irb->current_basic_block); + ir_ref_instruction(dest_ptr, ag->current_basic_block); + ir_ref_instruction(byte, ag->current_basic_block); + ir_ref_instruction(count, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_memcpy_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_memcpy_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *dest_ptr, IrInstSrc *src_ptr, IrInstSrc *count) { - IrInstSrcMemcpy *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcMemcpy *instruction = ir_build_instruction(ag, scope, source_node); instruction->dest_ptr = dest_ptr; instruction->src_ptr = src_ptr; instruction->count = count; - ir_ref_instruction(dest_ptr, irb->current_basic_block); - ir_ref_instruction(src_ptr, irb->current_basic_block); - ir_ref_instruction(count, irb->current_basic_block); + ir_ref_instruction(dest_ptr, ag->current_basic_block); + ir_ref_instruction(src_ptr, ag->current_basic_block); + ir_ref_instruction(count, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_slice_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_slice_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *ptr, IrInstSrc *start, IrInstSrc *end, IrInstSrc *sentinel, bool safety_check_on, ResultLoc *result_loc) { - IrInstSrcSlice *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcSlice *instruction = ir_build_instruction(ag, scope, source_node); instruction->ptr = ptr; instruction->start = start; instruction->end = end; @@ -2102,150 +2102,150 @@ static IrInstSrc *ir_build_slice_src(IrBuilderSrc *irb, Scope *scope, AstNode *s instruction->safety_check_on = safety_check_on; instruction->result_loc = result_loc; - ir_ref_instruction(ptr, irb->current_basic_block); - ir_ref_instruction(start, irb->current_basic_block); - if (end) ir_ref_instruction(end, irb->current_basic_block); - if (sentinel) ir_ref_instruction(sentinel, irb->current_basic_block); + ir_ref_instruction(ptr, ag->current_basic_block); + ir_ref_instruction(start, ag->current_basic_block); + if (end) ir_ref_instruction(end, ag->current_basic_block); + if (sentinel) ir_ref_instruction(sentinel, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_breakpoint(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { - IrInstSrcBreakpoint *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_breakpoint(Stage1AstGen *ag, Scope *scope, AstNode *source_node) { + IrInstSrcBreakpoint *instruction = ir_build_instruction(ag, scope, source_node); return &instruction->base; } -static IrInstSrc *ir_build_return_address_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { - IrInstSrcReturnAddress *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_return_address_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node) { + IrInstSrcReturnAddress *instruction = ir_build_instruction(ag, scope, source_node); return &instruction->base; } -static IrInstSrc *ir_build_frame_address_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { - IrInstSrcFrameAddress *inst = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_frame_address_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node) { + IrInstSrcFrameAddress *inst = ir_build_instruction(ag, scope, source_node); return &inst->base; } -static IrInstSrc *ir_build_handle_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { - IrInstSrcFrameHandle *inst = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_handle_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node) { + IrInstSrcFrameHandle *inst = ir_build_instruction(ag, scope, source_node); return &inst->base; } -static IrInstSrc *ir_build_frame_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *fn) { - IrInstSrcFrameType *inst = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_frame_type(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *fn) { + IrInstSrcFrameType *inst = ir_build_instruction(ag, scope, source_node); inst->fn = fn; - ir_ref_instruction(fn, irb->current_basic_block); + ir_ref_instruction(fn, ag->current_basic_block); return &inst->base; } -static IrInstSrc *ir_build_frame_size_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *fn) { - IrInstSrcFrameSize *inst = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_frame_size_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *fn) { + IrInstSrcFrameSize *inst = ir_build_instruction(ag, scope, source_node); inst->fn = fn; - ir_ref_instruction(fn, irb->current_basic_block); + ir_ref_instruction(fn, ag->current_basic_block); return &inst->base; } -static IrInstSrc *ir_build_overflow_op_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_overflow_op_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrOverflowOp op, IrInstSrc *type_value, IrInstSrc *op1, IrInstSrc *op2, IrInstSrc *result_ptr) { - IrInstSrcOverflowOp *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcOverflowOp *instruction = ir_build_instruction(ag, scope, source_node); instruction->op = op; instruction->type_value = type_value; instruction->op1 = op1; instruction->op2 = op2; instruction->result_ptr = result_ptr; - ir_ref_instruction(type_value, irb->current_basic_block); - ir_ref_instruction(op1, irb->current_basic_block); - ir_ref_instruction(op2, irb->current_basic_block); - ir_ref_instruction(result_ptr, irb->current_basic_block); + ir_ref_instruction(type_value, ag->current_basic_block); + ir_ref_instruction(op1, ag->current_basic_block); + ir_ref_instruction(op2, ag->current_basic_block); + ir_ref_instruction(result_ptr, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_float_op_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *operand, +static IrInstSrc *ir_build_float_op_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *operand, BuiltinFnId fn_id) { - IrInstSrcFloatOp *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcFloatOp *instruction = ir_build_instruction(ag, scope, source_node); instruction->operand = operand; instruction->fn_id = fn_id; - ir_ref_instruction(operand, irb->current_basic_block); + ir_ref_instruction(operand, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_mul_add_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_mul_add_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *type_value, IrInstSrc *op1, IrInstSrc *op2, IrInstSrc *op3) { - IrInstSrcMulAdd *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcMulAdd *instruction = ir_build_instruction(ag, scope, source_node); instruction->type_value = type_value; instruction->op1 = op1; instruction->op2 = op2; instruction->op3 = op3; - ir_ref_instruction(type_value, irb->current_basic_block); - ir_ref_instruction(op1, irb->current_basic_block); - ir_ref_instruction(op2, irb->current_basic_block); - ir_ref_instruction(op3, irb->current_basic_block); + ir_ref_instruction(type_value, ag->current_basic_block); + ir_ref_instruction(op1, ag->current_basic_block); + ir_ref_instruction(op2, ag->current_basic_block); + ir_ref_instruction(op3, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_align_of(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *type_value) { - IrInstSrcAlignOf *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_align_of(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *type_value) { + IrInstSrcAlignOf *instruction = ir_build_instruction(ag, scope, source_node); instruction->type_value = type_value; - ir_ref_instruction(type_value, irb->current_basic_block); + ir_ref_instruction(type_value, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_test_err_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_test_err_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *base_ptr, bool resolve_err_set, bool base_ptr_is_payload) { - IrInstSrcTestErr *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcTestErr *instruction = ir_build_instruction(ag, scope, source_node); instruction->base_ptr = base_ptr; instruction->resolve_err_set = resolve_err_set; instruction->base_ptr_is_payload = base_ptr_is_payload; - ir_ref_instruction(base_ptr, irb->current_basic_block); + ir_ref_instruction(base_ptr, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_unwrap_err_code_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_unwrap_err_code_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *err_union_ptr) { - IrInstSrcUnwrapErrCode *inst = ir_build_instruction(irb, scope, source_node); + IrInstSrcUnwrapErrCode *inst = ir_build_instruction(ag, scope, source_node); inst->err_union_ptr = err_union_ptr; - ir_ref_instruction(err_union_ptr, irb->current_basic_block); + ir_ref_instruction(err_union_ptr, ag->current_basic_block); return &inst->base; } -static IrInstSrc *ir_build_unwrap_err_payload_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_unwrap_err_payload_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *value, bool safety_check_on, bool initializing) { - IrInstSrcUnwrapErrPayload *inst = ir_build_instruction(irb, scope, source_node); + IrInstSrcUnwrapErrPayload *inst = ir_build_instruction(ag, scope, source_node); inst->value = value; inst->safety_check_on = safety_check_on; inst->initializing = initializing; - ir_ref_instruction(value, irb->current_basic_block); + ir_ref_instruction(value, ag->current_basic_block); return &inst->base; } -static IrInstSrc *ir_build_fn_proto(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_fn_proto(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc **param_types, IrInstSrc *align_value, IrInstSrc *callconv_value, IrInstSrc *return_type, bool is_var_args) { - IrInstSrcFnProto *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcFnProto *instruction = ir_build_instruction(ag, scope, source_node); instruction->param_types = param_types; instruction->align_value = align_value; instruction->callconv_value = callconv_value; @@ -2256,136 +2256,136 @@ static IrInstSrc *ir_build_fn_proto(IrBuilderSrc *irb, Scope *scope, AstNode *so size_t param_count = source_node->data.fn_proto.params.length; if (is_var_args) param_count -= 1; for (size_t i = 0; i < param_count; i += 1) { - if (param_types[i] != nullptr) ir_ref_instruction(param_types[i], irb->current_basic_block); + if (param_types[i] != nullptr) ir_ref_instruction(param_types[i], ag->current_basic_block); } - if (align_value != nullptr) ir_ref_instruction(align_value, irb->current_basic_block); - if (callconv_value != nullptr) ir_ref_instruction(callconv_value, irb->current_basic_block); - ir_ref_instruction(return_type, irb->current_basic_block); + if (align_value != nullptr) ir_ref_instruction(align_value, ag->current_basic_block); + if (callconv_value != nullptr) ir_ref_instruction(callconv_value, ag->current_basic_block); + ir_ref_instruction(return_type, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_test_comptime(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *value) { - IrInstSrcTestComptime *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_test_comptime(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *value) { + IrInstSrcTestComptime *instruction = ir_build_instruction(ag, scope, source_node); instruction->value = value; - ir_ref_instruction(value, irb->current_basic_block); + ir_ref_instruction(value, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_ptr_cast_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_ptr_cast_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *dest_type, IrInstSrc *ptr, bool safety_check_on) { IrInstSrcPtrCast *instruction = ir_build_instruction( - irb, scope, source_node); + ag, scope, source_node); instruction->dest_type = dest_type; instruction->ptr = ptr; instruction->safety_check_on = safety_check_on; - ir_ref_instruction(dest_type, irb->current_basic_block); - ir_ref_instruction(ptr, irb->current_basic_block); + ir_ref_instruction(dest_type, ag->current_basic_block); + ir_ref_instruction(ptr, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_implicit_cast(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_implicit_cast(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *operand, ResultLocCast *result_loc_cast) { - IrInstSrcImplicitCast *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcImplicitCast *instruction = ir_build_instruction(ag, scope, source_node); instruction->operand = operand; instruction->result_loc_cast = result_loc_cast; - ir_ref_instruction(operand, irb->current_basic_block); + ir_ref_instruction(operand, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_bit_cast_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_bit_cast_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *operand, ResultLocBitCast *result_loc_bit_cast) { - IrInstSrcBitCast *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcBitCast *instruction = ir_build_instruction(ag, scope, source_node); instruction->operand = operand; instruction->result_loc_bit_cast = result_loc_bit_cast; - ir_ref_instruction(operand, irb->current_basic_block); + ir_ref_instruction(operand, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_int_to_ptr_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_int_to_ptr_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *dest_type, IrInstSrc *target) { - IrInstSrcIntToPtr *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcIntToPtr *instruction = ir_build_instruction(ag, scope, source_node); instruction->dest_type = dest_type; instruction->target = target; - ir_ref_instruction(dest_type, irb->current_basic_block); - ir_ref_instruction(target, irb->current_basic_block); + ir_ref_instruction(dest_type, ag->current_basic_block); + ir_ref_instruction(target, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_ptr_to_int_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_ptr_to_int_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *target) { - IrInstSrcPtrToInt *inst = ir_build_instruction(irb, scope, source_node); + IrInstSrcPtrToInt *inst = ir_build_instruction(ag, scope, source_node); inst->target = target; - ir_ref_instruction(target, irb->current_basic_block); + ir_ref_instruction(target, ag->current_basic_block); return &inst->base; } -static IrInstSrc *ir_build_int_to_enum_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_int_to_enum_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *dest_type, IrInstSrc *target) { - IrInstSrcIntToEnum *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcIntToEnum *instruction = ir_build_instruction(ag, scope, source_node); instruction->dest_type = dest_type; instruction->target = target; - if (dest_type) ir_ref_instruction(dest_type, irb->current_basic_block); - ir_ref_instruction(target, irb->current_basic_block); + if (dest_type) ir_ref_instruction(dest_type, ag->current_basic_block); + ir_ref_instruction(target, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_enum_to_int(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_enum_to_int(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *target) { IrInstSrcEnumToInt *instruction = ir_build_instruction( - irb, scope, source_node); + ag, scope, source_node); instruction->target = target; - ir_ref_instruction(target, irb->current_basic_block); + ir_ref_instruction(target, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_int_to_err_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_int_to_err_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *target) { - IrInstSrcIntToErr *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcIntToErr *instruction = ir_build_instruction(ag, scope, source_node); instruction->target = target; - ir_ref_instruction(target, irb->current_basic_block); + ir_ref_instruction(target, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_err_to_int_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_err_to_int_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *target) { IrInstSrcErrToInt *instruction = ir_build_instruction( - irb, scope, source_node); + ag, scope, source_node); instruction->target = target; - ir_ref_instruction(target, irb->current_basic_block); + ir_ref_instruction(target, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_check_switch_prongs(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_check_switch_prongs(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *target_value, IrInstSrcCheckSwitchProngsRange *ranges, size_t range_count, AstNode* else_prong, bool have_underscore_prong) { @@ -2394,192 +2394,192 @@ static IrInstSrc *ir_build_check_switch_prongs(IrBuilderSrc *irb, Scope *scope, IrInstSrcIdCheckSwitchProngsUnderYes : IrInstSrcIdCheckSwitchProngsUnderNo; instruction->base.base.scope = scope; instruction->base.base.source_node = source_node; - instruction->base.base.debug_id = irb_next_debug_id(irb); - instruction->base.owner_bb = irb->current_basic_block; - ir_instruction_append(irb->current_basic_block, &instruction->base); + instruction->base.base.debug_id = irb_next_debug_id(ag); + instruction->base.owner_bb = ag->current_basic_block; + ir_instruction_append(ag->current_basic_block, &instruction->base); instruction->target_value = target_value; instruction->ranges = ranges; instruction->range_count = range_count; instruction->else_prong = else_prong; - ir_ref_instruction(target_value, irb->current_basic_block); + ir_ref_instruction(target_value, ag->current_basic_block); for (size_t i = 0; i < range_count; i += 1) { - ir_ref_instruction(ranges[i].start, irb->current_basic_block); - ir_ref_instruction(ranges[i].end, irb->current_basic_block); + ir_ref_instruction(ranges[i].start, ag->current_basic_block); + ir_ref_instruction(ranges[i].end, ag->current_basic_block); } return &instruction->base; } -static IrInstSrc *ir_build_check_statement_is_void(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_check_statement_is_void(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc* statement_value) { IrInstSrcCheckStatementIsVoid *instruction = ir_build_instruction( - irb, scope, source_node); + ag, scope, source_node); instruction->statement_value = statement_value; - ir_ref_instruction(statement_value, irb->current_basic_block); + ir_ref_instruction(statement_value, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_type_name(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_type_name(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *type_value) { - IrInstSrcTypeName *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcTypeName *instruction = ir_build_instruction(ag, scope, source_node); instruction->type_value = type_value; - ir_ref_instruction(type_value, irb->current_basic_block); + ir_ref_instruction(type_value, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_decl_ref(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, Tld *tld, LVal lval) { - IrInstSrcDeclRef *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_decl_ref(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Tld *tld, LVal lval) { + IrInstSrcDeclRef *instruction = ir_build_instruction(ag, scope, source_node); instruction->tld = tld; instruction->lval = lval; return &instruction->base; } -static IrInstSrc *ir_build_panic_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *msg) { - IrInstSrcPanic *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_panic_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *msg) { + IrInstSrcPanic *instruction = ir_build_instruction(ag, scope, source_node); instruction->base.is_noreturn = true; instruction->msg = msg; - ir_ref_instruction(msg, irb->current_basic_block); + ir_ref_instruction(msg, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_tag_name_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *target) { - IrInstSrcTagName *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_tag_name_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *target) { + IrInstSrcTagName *instruction = ir_build_instruction(ag, scope, source_node); instruction->target = target; - ir_ref_instruction(target, irb->current_basic_block); + ir_ref_instruction(target, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_field_parent_ptr_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_field_parent_ptr_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *type_value, IrInstSrc *field_name, IrInstSrc *field_ptr) { IrInstSrcFieldParentPtr *inst = ir_build_instruction( - irb, scope, source_node); + ag, scope, source_node); inst->type_value = type_value; inst->field_name = field_name; inst->field_ptr = field_ptr; - ir_ref_instruction(type_value, irb->current_basic_block); - ir_ref_instruction(field_name, irb->current_basic_block); - ir_ref_instruction(field_ptr, irb->current_basic_block); + ir_ref_instruction(type_value, ag->current_basic_block); + ir_ref_instruction(field_name, ag->current_basic_block); + ir_ref_instruction(field_ptr, ag->current_basic_block); return &inst->base; } -static IrInstSrc *ir_build_byte_offset_of(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_byte_offset_of(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *type_value, IrInstSrc *field_name) { - IrInstSrcByteOffsetOf *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcByteOffsetOf *instruction = ir_build_instruction(ag, scope, source_node); instruction->type_value = type_value; instruction->field_name = field_name; - ir_ref_instruction(type_value, irb->current_basic_block); - ir_ref_instruction(field_name, irb->current_basic_block); + ir_ref_instruction(type_value, ag->current_basic_block); + ir_ref_instruction(field_name, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_bit_offset_of(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_bit_offset_of(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *type_value, IrInstSrc *field_name) { - IrInstSrcBitOffsetOf *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcBitOffsetOf *instruction = ir_build_instruction(ag, scope, source_node); instruction->type_value = type_value; instruction->field_name = field_name; - ir_ref_instruction(type_value, irb->current_basic_block); - ir_ref_instruction(field_name, irb->current_basic_block); + ir_ref_instruction(type_value, ag->current_basic_block); + ir_ref_instruction(field_name, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_type_info(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *type_value) { - IrInstSrcTypeInfo *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_type_info(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *type_value) { + IrInstSrcTypeInfo *instruction = ir_build_instruction(ag, scope, source_node); instruction->type_value = type_value; - ir_ref_instruction(type_value, irb->current_basic_block); + ir_ref_instruction(type_value, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *type_info) { - IrInstSrcType *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_type(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *type_info) { + IrInstSrcType *instruction = ir_build_instruction(ag, scope, source_node); instruction->type_info = type_info; - ir_ref_instruction(type_info, irb->current_basic_block); + ir_ref_instruction(type_info, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_set_eval_branch_quota(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_set_eval_branch_quota(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *new_quota) { - IrInstSrcSetEvalBranchQuota *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcSetEvalBranchQuota *instruction = ir_build_instruction(ag, scope, source_node); instruction->new_quota = new_quota; - ir_ref_instruction(new_quota, irb->current_basic_block); + ir_ref_instruction(new_quota, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_align_cast_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_align_cast_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *align_bytes, IrInstSrc *target) { - IrInstSrcAlignCast *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcAlignCast *instruction = ir_build_instruction(ag, scope, source_node); instruction->align_bytes = align_bytes; instruction->target = target; - ir_ref_instruction(align_bytes, irb->current_basic_block); - ir_ref_instruction(target, irb->current_basic_block); + ir_ref_instruction(align_bytes, ag->current_basic_block); + ir_ref_instruction(target, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_resolve_result(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_resolve_result(Stage1AstGen *ag, Scope *scope, AstNode *source_node, ResultLoc *result_loc, IrInstSrc *ty) { - IrInstSrcResolveResult *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcResolveResult *instruction = ir_build_instruction(ag, scope, source_node); instruction->result_loc = result_loc; instruction->ty = ty; - if (ty != nullptr) ir_ref_instruction(ty, irb->current_basic_block); + if (ty != nullptr) ir_ref_instruction(ty, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_reset_result(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_reset_result(Stage1AstGen *ag, Scope *scope, AstNode *source_node, ResultLoc *result_loc) { - IrInstSrcResetResult *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcResetResult *instruction = ir_build_instruction(ag, scope, source_node); instruction->result_loc = result_loc; instruction->base.is_gen = true; return &instruction->base; } -static IrInstSrc *ir_build_set_align_stack(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_set_align_stack(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *align_bytes) { - IrInstSrcSetAlignStack *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcSetAlignStack *instruction = ir_build_instruction(ag, scope, source_node); instruction->align_bytes = align_bytes; - ir_ref_instruction(align_bytes, irb->current_basic_block); + ir_ref_instruction(align_bytes, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_arg_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_arg_type(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *fn_type, IrInstSrc *arg_index, bool allow_var) { IrInstSrcArgType *instruction = heap::c_allocator.create(); @@ -2587,273 +2587,273 @@ static IrInstSrc *ir_build_arg_type(IrBuilderSrc *irb, Scope *scope, AstNode *so IrInstSrcIdArgTypeAllowVarTrue : IrInstSrcIdArgTypeAllowVarFalse; instruction->base.base.scope = scope; instruction->base.base.source_node = source_node; - instruction->base.base.debug_id = irb_next_debug_id(irb); - instruction->base.owner_bb = irb->current_basic_block; - ir_instruction_append(irb->current_basic_block, &instruction->base); + instruction->base.base.debug_id = irb_next_debug_id(ag); + instruction->base.owner_bb = ag->current_basic_block; + ir_instruction_append(ag->current_basic_block, &instruction->base); instruction->fn_type = fn_type; instruction->arg_index = arg_index; - ir_ref_instruction(fn_type, irb->current_basic_block); - ir_ref_instruction(arg_index, irb->current_basic_block); + ir_ref_instruction(fn_type, ag->current_basic_block); + ir_ref_instruction(arg_index, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_error_return_trace_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_error_return_trace_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstErrorReturnTraceOptional optional) { - IrInstSrcErrorReturnTrace *inst = ir_build_instruction(irb, scope, source_node); + IrInstSrcErrorReturnTrace *inst = ir_build_instruction(ag, scope, source_node); inst->optional = optional; return &inst->base; } -static IrInstSrc *ir_build_error_union(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_error_union(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *err_set, IrInstSrc *payload) { - IrInstSrcErrorUnion *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcErrorUnion *instruction = ir_build_instruction(ag, scope, source_node); instruction->err_set = err_set; instruction->payload = payload; - ir_ref_instruction(err_set, irb->current_basic_block); - ir_ref_instruction(payload, irb->current_basic_block); + ir_ref_instruction(err_set, ag->current_basic_block); + ir_ref_instruction(payload, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_atomic_rmw_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_atomic_rmw_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *operand_type, IrInstSrc *ptr, IrInstSrc *op, IrInstSrc *operand, IrInstSrc *ordering) { - IrInstSrcAtomicRmw *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcAtomicRmw *instruction = ir_build_instruction(ag, scope, source_node); instruction->operand_type = operand_type; instruction->ptr = ptr; instruction->op = op; instruction->operand = operand; instruction->ordering = ordering; - ir_ref_instruction(operand_type, irb->current_basic_block); - ir_ref_instruction(ptr, irb->current_basic_block); - ir_ref_instruction(op, irb->current_basic_block); - ir_ref_instruction(operand, irb->current_basic_block); - ir_ref_instruction(ordering, irb->current_basic_block); + ir_ref_instruction(operand_type, ag->current_basic_block); + ir_ref_instruction(ptr, ag->current_basic_block); + ir_ref_instruction(op, ag->current_basic_block); + ir_ref_instruction(operand, ag->current_basic_block); + ir_ref_instruction(ordering, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_atomic_load_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_atomic_load_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *operand_type, IrInstSrc *ptr, IrInstSrc *ordering) { - IrInstSrcAtomicLoad *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcAtomicLoad *instruction = ir_build_instruction(ag, scope, source_node); instruction->operand_type = operand_type; instruction->ptr = ptr; instruction->ordering = ordering; - ir_ref_instruction(operand_type, irb->current_basic_block); - ir_ref_instruction(ptr, irb->current_basic_block); - ir_ref_instruction(ordering, irb->current_basic_block); + ir_ref_instruction(operand_type, ag->current_basic_block); + ir_ref_instruction(ptr, ag->current_basic_block); + ir_ref_instruction(ordering, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_atomic_store_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_atomic_store_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *operand_type, IrInstSrc *ptr, IrInstSrc *value, IrInstSrc *ordering) { - IrInstSrcAtomicStore *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcAtomicStore *instruction = ir_build_instruction(ag, scope, source_node); instruction->operand_type = operand_type; instruction->ptr = ptr; instruction->value = value; instruction->ordering = ordering; - ir_ref_instruction(operand_type, irb->current_basic_block); - ir_ref_instruction(ptr, irb->current_basic_block); - ir_ref_instruction(value, irb->current_basic_block); - ir_ref_instruction(ordering, irb->current_basic_block); + ir_ref_instruction(operand_type, ag->current_basic_block); + ir_ref_instruction(ptr, ag->current_basic_block); + ir_ref_instruction(value, ag->current_basic_block); + ir_ref_instruction(ordering, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_save_err_ret_addr_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { - IrInstSrcSaveErrRetAddr *inst = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_save_err_ret_addr_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node) { + IrInstSrcSaveErrRetAddr *inst = ir_build_instruction(ag, scope, source_node); return &inst->base; } -static IrInstSrc *ir_build_add_implicit_return_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_add_implicit_return_type(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *value, ResultLocReturn *result_loc_ret) { - IrInstSrcAddImplicitReturnType *inst = ir_build_instruction(irb, scope, source_node); + IrInstSrcAddImplicitReturnType *inst = ir_build_instruction(ag, scope, source_node); inst->value = value; inst->result_loc_ret = result_loc_ret; - ir_ref_instruction(value, irb->current_basic_block); + ir_ref_instruction(value, ag->current_basic_block); return &inst->base; } -static IrInstSrc *ir_build_has_decl(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_has_decl(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *container, IrInstSrc *name) { - IrInstSrcHasDecl *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcHasDecl *instruction = ir_build_instruction(ag, scope, source_node); instruction->container = container; instruction->name = name; - ir_ref_instruction(container, irb->current_basic_block); - ir_ref_instruction(name, irb->current_basic_block); + ir_ref_instruction(container, ag->current_basic_block); + ir_ref_instruction(name, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_undeclared_identifier(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, Buf *name) { - IrInstSrcUndeclaredIdent *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_undeclared_identifier(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Buf *name) { + IrInstSrcUndeclaredIdent *instruction = ir_build_instruction(ag, scope, source_node); instruction->name = name; return &instruction->base; } -static IrInstSrc *ir_build_check_runtime_scope(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *scope_is_comptime, IrInstSrc *is_comptime) { - IrInstSrcCheckRuntimeScope *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_check_runtime_scope(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *scope_is_comptime, IrInstSrc *is_comptime) { + IrInstSrcCheckRuntimeScope *instruction = ir_build_instruction(ag, scope, source_node); instruction->scope_is_comptime = scope_is_comptime; instruction->is_comptime = is_comptime; - ir_ref_instruction(scope_is_comptime, irb->current_basic_block); - ir_ref_instruction(is_comptime, irb->current_basic_block); + ir_ref_instruction(scope_is_comptime, ag->current_basic_block); + ir_ref_instruction(is_comptime, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_union_init_named_field(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_union_init_named_field(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *union_type, IrInstSrc *field_name, IrInstSrc *field_result_loc, IrInstSrc *result_loc) { - IrInstSrcUnionInitNamedField *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcUnionInitNamedField *instruction = ir_build_instruction(ag, scope, source_node); instruction->union_type = union_type; instruction->field_name = field_name; instruction->field_result_loc = field_result_loc; instruction->result_loc = result_loc; - ir_ref_instruction(union_type, irb->current_basic_block); - ir_ref_instruction(field_name, irb->current_basic_block); - ir_ref_instruction(field_result_loc, irb->current_basic_block); - if (result_loc != nullptr) ir_ref_instruction(result_loc, irb->current_basic_block); + ir_ref_instruction(union_type, ag->current_basic_block); + ir_ref_instruction(field_name, ag->current_basic_block); + ir_ref_instruction(field_result_loc, ag->current_basic_block); + if (result_loc != nullptr) ir_ref_instruction(result_loc, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_alloca_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_alloca_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *align, const char *name_hint, IrInstSrc *is_comptime) { - IrInstSrcAlloca *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcAlloca *instruction = ir_build_instruction(ag, scope, source_node); instruction->base.is_gen = true; instruction->align = align; instruction->name_hint = name_hint; instruction->is_comptime = is_comptime; - if (align != nullptr) ir_ref_instruction(align, irb->current_basic_block); - if (is_comptime != nullptr) ir_ref_instruction(is_comptime, irb->current_basic_block); + if (align != nullptr) ir_ref_instruction(align, ag->current_basic_block); + if (is_comptime != nullptr) ir_ref_instruction(is_comptime, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_end_expr(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_end_expr(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *value, ResultLoc *result_loc) { - IrInstSrcEndExpr *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcEndExpr *instruction = ir_build_instruction(ag, scope, source_node); instruction->base.is_gen = true; instruction->value = value; instruction->result_loc = result_loc; - ir_ref_instruction(value, irb->current_basic_block); + ir_ref_instruction(value, ag->current_basic_block); return &instruction->base; } -static IrInstSrcSuspendBegin *ir_build_suspend_begin_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { - return ir_build_instruction(irb, scope, source_node); +static IrInstSrcSuspendBegin *ir_build_suspend_begin_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node) { + return ir_build_instruction(ag, scope, source_node); } -static IrInstSrc *ir_build_suspend_finish_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_suspend_finish_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrcSuspendBegin *begin) { - IrInstSrcSuspendFinish *inst = ir_build_instruction(irb, scope, source_node); + IrInstSrcSuspendFinish *inst = ir_build_instruction(ag, scope, source_node); inst->begin = begin; - ir_ref_instruction(&begin->base, irb->current_basic_block); + ir_ref_instruction(&begin->base, ag->current_basic_block); return &inst->base; } -static IrInstSrc *ir_build_await_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_await_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *frame, ResultLoc *result_loc, bool is_nosuspend) { - IrInstSrcAwait *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcAwait *instruction = ir_build_instruction(ag, scope, source_node); instruction->frame = frame; instruction->result_loc = result_loc; instruction->is_nosuspend = is_nosuspend; - ir_ref_instruction(frame, irb->current_basic_block); + ir_ref_instruction(frame, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_resume_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *frame) { - IrInstSrcResume *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_resume_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *frame) { + IrInstSrcResume *instruction = ir_build_instruction(ag, scope, source_node); instruction->frame = frame; - ir_ref_instruction(frame, irb->current_basic_block); + ir_ref_instruction(frame, ag->current_basic_block); return &instruction->base; } -static IrInstSrcSpillBegin *ir_build_spill_begin_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrcSpillBegin *ir_build_spill_begin_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *operand, SpillId spill_id) { - IrInstSrcSpillBegin *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcSpillBegin *instruction = ir_build_instruction(ag, scope, source_node); instruction->operand = operand; instruction->spill_id = spill_id; - ir_ref_instruction(operand, irb->current_basic_block); + ir_ref_instruction(operand, ag->current_basic_block); return instruction; } -static IrInstSrc *ir_build_spill_end_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_spill_end_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrcSpillBegin *begin) { - IrInstSrcSpillEnd *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcSpillEnd *instruction = ir_build_instruction(ag, scope, source_node); instruction->begin = begin; - ir_ref_instruction(&begin->base, irb->current_basic_block); + ir_ref_instruction(&begin->base, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_wasm_memory_size_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *index) { - IrInstSrcWasmMemorySize *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_wasm_memory_size_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *index) { + IrInstSrcWasmMemorySize *instruction = ir_build_instruction(ag, scope, source_node); instruction->index = index; - ir_ref_instruction(index, irb->current_basic_block); + ir_ref_instruction(index, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_wasm_memory_grow_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *index, IrInstSrc *delta) { - IrInstSrcWasmMemoryGrow *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_wasm_memory_grow_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *index, IrInstSrc *delta) { + IrInstSrcWasmMemoryGrow *instruction = ir_build_instruction(ag, scope, source_node); instruction->index = index; instruction->delta = delta; - ir_ref_instruction(index, irb->current_basic_block); - ir_ref_instruction(delta, irb->current_basic_block); + ir_ref_instruction(index, ag->current_basic_block); + ir_ref_instruction(delta, ag->current_basic_block); return &instruction->base; } -static IrInstSrc *ir_build_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { - IrInstSrcSrc *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node) { + IrInstSrcSrc *instruction = ir_build_instruction(ag, scope, source_node); return &instruction->base; } -static void ir_count_defers(IrBuilderSrc *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { +static void ir_count_defers(Stage1AstGen *ag, Scope *inner_scope, Scope *outer_scope, size_t *results) { results[ReturnKindUnconditional] = 0; results[ReturnKindError] = 0; @@ -2896,7 +2896,7 @@ static IrInstSrc *ir_mark_gen(IrInstSrc *instruction) { return instruction; } -static bool ir_gen_defers_for_block(IrBuilderSrc *irb, Scope *inner_scope, Scope *outer_scope, bool *is_noreturn, IrInstSrc *err_value) { +static bool ir_gen_defers_for_block(Stage1AstGen *ag, Scope *inner_scope, Scope *outer_scope, bool *is_noreturn, IrInstSrc *err_value) { Scope *scope = inner_scope; if (is_noreturn != nullptr) *is_noreturn = false; while (scope != outer_scope) { @@ -2925,36 +2925,36 @@ static bool ir_gen_defers_for_block(IrBuilderSrc *irb, Scope *inner_scope, Scope Buf *var_name = node_identifier_buf(defer_var_node); if (defer_expr_node->type == NodeTypeUnreachable) { - add_node_error(irb->codegen, defer_var_node, + add_node_error(ag->codegen, defer_var_node, buf_sprintf("unused variable: '%s'", buf_ptr(var_name))); return false; } IrInstSrc *is_comptime; - if (ir_should_inline(irb->exec, defer_expr_scope)) { - is_comptime = ir_build_const_bool(irb, defer_expr_scope, + if (ir_should_inline(ag->exec, defer_expr_scope)) { + is_comptime = ir_build_const_bool(ag, defer_expr_scope, defer_expr_node, true); } else { - is_comptime = ir_build_test_comptime(irb, defer_expr_scope, + is_comptime = ir_build_test_comptime(ag, defer_expr_scope, defer_expr_node, err_value); } - ZigVar *err_var = ir_create_var(irb, defer_var_node, defer_expr_scope, + ZigVar *err_var = ir_create_var(ag, defer_var_node, defer_expr_scope, var_name, true, true, false, is_comptime); - build_decl_var_and_init(irb, defer_expr_scope, defer_var_node, err_var, err_value, + build_decl_var_and_init(ag, defer_expr_scope, defer_var_node, err_var, err_value, buf_ptr(var_name), is_comptime); defer_expr_scope = err_var->child_scope; } - IrInstSrc *defer_expr_value = ir_gen_node(irb, defer_expr_node, defer_expr_scope); - if (defer_expr_value == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; + IrInstSrc *defer_expr_value = ir_gen_node(ag, defer_expr_node, defer_expr_scope); + if (defer_expr_value == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; if (defer_expr_value->is_noreturn) { if (is_noreturn != nullptr) *is_noreturn = true; } else { - ir_mark_gen(ir_build_check_statement_is_void(irb, defer_expr_scope, defer_expr_node, + ir_mark_gen(ir_build_check_statement_is_void(ag, defer_expr_scope, defer_expr_node, defer_expr_value)); } scope = scope->parent; @@ -2982,15 +2982,15 @@ static bool ir_gen_defers_for_block(IrBuilderSrc *irb, Scope *inner_scope, Scope return true; } -static void ir_set_cursor_at_end(IrBuilderSrc *irb, IrBasicBlockSrc *basic_block) { +static void ir_set_cursor_at_end(Stage1AstGen *ag, IrBasicBlockSrc *basic_block) { assert(basic_block); - irb->current_basic_block = basic_block; + ag->current_basic_block = basic_block; } -static void ir_set_cursor_at_end_and_append_block(IrBuilderSrc *irb, IrBasicBlockSrc *basic_block) { - basic_block->index = irb->exec->basic_block_list.length; - irb->exec->basic_block_list.append(basic_block); - ir_set_cursor_at_end(irb, basic_block); +static void ir_set_cursor_at_end_and_append_block(Stage1AstGen *ag, IrBasicBlockSrc *basic_block) { + basic_block->index = ag->exec->basic_block_list.length; + ag->exec->basic_block_list.append(basic_block); + ir_set_cursor_at_end(ag, basic_block); } static ScopeSuspend *get_scope_suspend(Scope *scope) { @@ -3017,19 +3017,19 @@ static ScopeDeferExpr *get_scope_defer_expr(Scope *scope) { return nullptr; } -static IrInstSrc *ir_gen_return(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { +static IrInstSrc *ir_gen_return(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypeReturnExpr); ScopeDeferExpr *scope_defer_expr = get_scope_defer_expr(scope); if (scope_defer_expr) { if (!scope_defer_expr->reported_err) { - add_node_error(irb->codegen, node, buf_sprintf("cannot return from defer expression")); + add_node_error(ag->codegen, node, buf_sprintf("cannot return from defer expression")); scope_defer_expr->reported_err = true; } - return irb->codegen->invalid_inst_src; + return ag->codegen->invalid_inst_src; } - Scope *outer_scope = irb->exec->begin_scope; + Scope *outer_scope = ag->exec->begin_scope; AstNode *expr_node = node->data.return_expr.expr; switch (node->data.return_expr.kind) { @@ -3037,119 +3037,119 @@ static IrInstSrc *ir_gen_return(IrBuilderSrc *irb, Scope *scope, AstNode *node, { ResultLocReturn *result_loc_ret = heap::c_allocator.create(); result_loc_ret->base.id = ResultLocIdReturn; - ir_build_reset_result(irb, scope, node, &result_loc_ret->base); + ir_build_reset_result(ag, scope, node, &result_loc_ret->base); IrInstSrc *return_value; if (expr_node) { // Temporarily set this so that if we return a type it gets the name of the function - ZigFn *prev_name_fn = irb->exec->name_fn; - irb->exec->name_fn = exec_fn_entry(irb->exec); - return_value = ir_gen_node_extra(irb, expr_node, scope, LValNone, &result_loc_ret->base); - irb->exec->name_fn = prev_name_fn; - if (return_value == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; + ZigFn *prev_name_fn = ag->exec->name_fn; + ag->exec->name_fn = exec_fn_entry(ag->exec); + return_value = ir_gen_node_extra(ag, expr_node, scope, LValNone, &result_loc_ret->base); + ag->exec->name_fn = prev_name_fn; + if (return_value == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; } else { - return_value = ir_build_const_void(irb, scope, node); - ir_build_end_expr(irb, scope, node, return_value, &result_loc_ret->base); + return_value = ir_build_const_void(ag, scope, node); + ir_build_end_expr(ag, scope, node, return_value, &result_loc_ret->base); } - ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, node, return_value, result_loc_ret)); + ir_mark_gen(ir_build_add_implicit_return_type(ag, scope, node, return_value, result_loc_ret)); size_t defer_counts[2]; - ir_count_defers(irb, scope, outer_scope, defer_counts); + ir_count_defers(ag, scope, outer_scope, defer_counts); bool have_err_defers = defer_counts[ReturnKindError] > 0; - if (!have_err_defers && !irb->codegen->have_err_ret_tracing) { + if (!have_err_defers && !ag->codegen->have_err_ret_tracing) { // only generate unconditional defers - if (!ir_gen_defers_for_block(irb, scope, outer_scope, nullptr, nullptr)) - return irb->codegen->invalid_inst_src; - IrInstSrc *result = ir_build_return_src(irb, scope, node, nullptr); + if (!ir_gen_defers_for_block(ag, scope, outer_scope, nullptr, nullptr)) + return ag->codegen->invalid_inst_src; + IrInstSrc *result = ir_build_return_src(ag, scope, node, nullptr); result_loc_ret->base.source_instruction = result; return result; } - bool should_inline = ir_should_inline(irb->exec, scope); + bool should_inline = ir_should_inline(ag->exec, scope); - IrBasicBlockSrc *err_block = ir_create_basic_block(irb, scope, "ErrRetErr"); - IrBasicBlockSrc *ok_block = ir_create_basic_block(irb, scope, "ErrRetOk"); + IrBasicBlockSrc *err_block = ir_create_basic_block(ag, scope, "ErrRetErr"); + IrBasicBlockSrc *ok_block = ir_create_basic_block(ag, scope, "ErrRetOk"); - IrInstSrc *is_err = ir_build_test_err_src(irb, scope, node, return_value, false, true); + IrInstSrc *is_err = ir_build_test_err_src(ag, scope, node, return_value, false, true); IrInstSrc *is_comptime; if (should_inline) { - is_comptime = ir_build_const_bool(irb, scope, node, should_inline); + is_comptime = ir_build_const_bool(ag, scope, node, should_inline); } else { - is_comptime = ir_build_test_comptime(irb, scope, node, is_err); + is_comptime = ir_build_test_comptime(ag, scope, node, is_err); } - ir_mark_gen(ir_build_cond_br(irb, scope, node, is_err, err_block, ok_block, is_comptime)); - IrBasicBlockSrc *ret_stmt_block = ir_create_basic_block(irb, scope, "RetStmt"); + ir_mark_gen(ir_build_cond_br(ag, scope, node, is_err, err_block, ok_block, is_comptime)); + IrBasicBlockSrc *ret_stmt_block = ir_create_basic_block(ag, scope, "RetStmt"); - ir_set_cursor_at_end_and_append_block(irb, err_block); - if (!ir_gen_defers_for_block(irb, scope, outer_scope, nullptr, return_value)) - return irb->codegen->invalid_inst_src; - if (irb->codegen->have_err_ret_tracing && !should_inline) { - ir_build_save_err_ret_addr_src(irb, scope, node); + ir_set_cursor_at_end_and_append_block(ag, err_block); + if (!ir_gen_defers_for_block(ag, scope, outer_scope, nullptr, return_value)) + return ag->codegen->invalid_inst_src; + if (ag->codegen->have_err_ret_tracing && !should_inline) { + ir_build_save_err_ret_addr_src(ag, scope, node); } - ir_build_br(irb, scope, node, ret_stmt_block, is_comptime); + ir_build_br(ag, scope, node, ret_stmt_block, is_comptime); - ir_set_cursor_at_end_and_append_block(irb, ok_block); - if (!ir_gen_defers_for_block(irb, scope, outer_scope, nullptr, nullptr)) - return irb->codegen->invalid_inst_src; - ir_build_br(irb, scope, node, ret_stmt_block, is_comptime); + ir_set_cursor_at_end_and_append_block(ag, ok_block); + if (!ir_gen_defers_for_block(ag, scope, outer_scope, nullptr, nullptr)) + return ag->codegen->invalid_inst_src; + ir_build_br(ag, scope, node, ret_stmt_block, is_comptime); - ir_set_cursor_at_end_and_append_block(irb, ret_stmt_block); - IrInstSrc *result = ir_build_return_src(irb, scope, node, nullptr); + ir_set_cursor_at_end_and_append_block(ag, ret_stmt_block); + IrInstSrc *result = ir_build_return_src(ag, scope, node, nullptr); result_loc_ret->base.source_instruction = result; return result; } case ReturnKindError: { assert(expr_node); - IrInstSrc *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr); - if (err_union_ptr == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - IrInstSrc *is_err_val = ir_build_test_err_src(irb, scope, node, err_union_ptr, true, false); + IrInstSrc *err_union_ptr = ir_gen_node_extra(ag, expr_node, scope, LValPtr, nullptr); + if (err_union_ptr == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; + IrInstSrc *is_err_val = ir_build_test_err_src(ag, scope, node, err_union_ptr, true, false); - IrBasicBlockSrc *return_block = ir_create_basic_block(irb, scope, "ErrRetReturn"); - IrBasicBlockSrc *continue_block = ir_create_basic_block(irb, scope, "ErrRetContinue"); + IrBasicBlockSrc *return_block = ir_create_basic_block(ag, scope, "ErrRetReturn"); + IrBasicBlockSrc *continue_block = ir_create_basic_block(ag, scope, "ErrRetContinue"); IrInstSrc *is_comptime; - bool should_inline = ir_should_inline(irb->exec, scope); + bool should_inline = ir_should_inline(ag->exec, scope); if (should_inline) { - is_comptime = ir_build_const_bool(irb, scope, node, true); + is_comptime = ir_build_const_bool(ag, scope, node, true); } else { - is_comptime = ir_build_test_comptime(irb, scope, node, is_err_val); + is_comptime = ir_build_test_comptime(ag, scope, node, is_err_val); } - ir_mark_gen(ir_build_cond_br(irb, scope, node, is_err_val, return_block, continue_block, is_comptime)); + ir_mark_gen(ir_build_cond_br(ag, scope, node, is_err_val, return_block, continue_block, is_comptime)); - ir_set_cursor_at_end_and_append_block(irb, return_block); - IrInstSrc *err_val_ptr = ir_build_unwrap_err_code_src(irb, scope, node, err_union_ptr); - IrInstSrc *err_val = ir_build_load_ptr(irb, scope, node, err_val_ptr); - ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, node, err_val, nullptr)); - IrInstSrcSpillBegin *spill_begin = ir_build_spill_begin_src(irb, scope, node, err_val, + ir_set_cursor_at_end_and_append_block(ag, return_block); + IrInstSrc *err_val_ptr = ir_build_unwrap_err_code_src(ag, scope, node, err_union_ptr); + IrInstSrc *err_val = ir_build_load_ptr(ag, scope, node, err_val_ptr); + ir_mark_gen(ir_build_add_implicit_return_type(ag, scope, node, err_val, nullptr)); + IrInstSrcSpillBegin *spill_begin = ir_build_spill_begin_src(ag, scope, node, err_val, SpillIdRetErrCode); ResultLocReturn *result_loc_ret = heap::c_allocator.create(); result_loc_ret->base.id = ResultLocIdReturn; - ir_build_reset_result(irb, scope, node, &result_loc_ret->base); - ir_build_end_expr(irb, scope, node, err_val, &result_loc_ret->base); + ir_build_reset_result(ag, scope, node, &result_loc_ret->base); + ir_build_end_expr(ag, scope, node, err_val, &result_loc_ret->base); bool is_noreturn = false; - if (!ir_gen_defers_for_block(irb, scope, outer_scope, &is_noreturn, err_val)) { - return irb->codegen->invalid_inst_src; + if (!ir_gen_defers_for_block(ag, scope, outer_scope, &is_noreturn, err_val)) { + return ag->codegen->invalid_inst_src; } if (!is_noreturn) { - if (irb->codegen->have_err_ret_tracing && !should_inline) { - ir_build_save_err_ret_addr_src(irb, scope, node); + if (ag->codegen->have_err_ret_tracing && !should_inline) { + ir_build_save_err_ret_addr_src(ag, scope, node); } - err_val = ir_build_spill_end_src(irb, scope, node, spill_begin); - IrInstSrc *ret_inst = ir_build_return_src(irb, scope, node, err_val); + err_val = ir_build_spill_end_src(ag, scope, node, spill_begin); + IrInstSrc *ret_inst = ir_build_return_src(ag, scope, node, err_val); result_loc_ret->base.source_instruction = ret_inst; } - ir_set_cursor_at_end_and_append_block(irb, continue_block); - IrInstSrc *unwrapped_ptr = ir_build_unwrap_err_payload_src(irb, scope, node, err_union_ptr, false, false); + ir_set_cursor_at_end_and_append_block(ag, continue_block); + IrInstSrc *unwrapped_ptr = ir_build_unwrap_err_payload_src(ag, scope, node, err_union_ptr, false, false); if (lval == LValPtr) return unwrapped_ptr; else - return ir_expr_wrap(irb, scope, ir_build_load_ptr(irb, scope, node, unwrapped_ptr), result_loc); + return ir_expr_wrap(ag, scope, ir_build_load_ptr(ag, scope, node, unwrapped_ptr), result_loc); } } zig_unreachable(); @@ -3227,11 +3227,11 @@ ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_scope, // Set name to nullptr to make the variable anonymous (not visible to programmer). // After you call this function var->child_scope has the variable in scope -static ZigVar *ir_create_var(IrBuilderSrc *irb, AstNode *node, Scope *scope, Buf *name, +static ZigVar *ir_create_var(Stage1AstGen *ag, AstNode *node, Scope *scope, Buf *name, bool src_is_const, bool gen_is_const, bool is_shadowable, IrInstSrc *is_comptime) { bool is_underscored = name ? buf_eql_str(name, "_") : false; - ZigVar *var = create_local_var(irb->codegen, node, scope, + ZigVar *var = create_local_var(ag->codegen, node, scope, (is_underscored ? nullptr : name), src_is_const, gen_is_const, (is_underscored ? true : is_shadowable), is_comptime, false); assert(var->child_scope); @@ -3266,7 +3266,7 @@ static bool is_duplicate_label(CodeGen *g, Scope *scope, AstNode *node, Buf *nam return false; } -static IrInstSrc *ir_gen_block(IrBuilderSrc *irb, Scope *parent_scope, AstNode *block_node, LVal lval, +static IrInstSrc *ir_gen_block(Stage1AstGen *ag, Scope *parent_scope, AstNode *block_node, LVal lval, ResultLoc *result_loc) { assert(block_node->type == NodeTypeBlock); @@ -3274,10 +3274,10 @@ static IrInstSrc *ir_gen_block(IrBuilderSrc *irb, Scope *parent_scope, AstNode * ZigList incoming_values = {0}; ZigList incoming_blocks = {0}; - if (is_duplicate_label(irb->codegen, parent_scope, block_node, block_node->data.block.name)) - return irb->codegen->invalid_inst_src; + if (is_duplicate_label(ag->codegen, parent_scope, block_node, block_node->data.block.name)) + return ag->codegen->invalid_inst_src; - ScopeBlock *scope_block = create_block_scope(irb->codegen, block_node, parent_scope); + ScopeBlock *scope_block = create_block_scope(ag->codegen, block_node, parent_scope); Scope *outer_block_scope = &scope_block->base; Scope *child_scope = outer_block_scope; @@ -3289,19 +3289,19 @@ static IrInstSrc *ir_gen_block(IrBuilderSrc *irb, Scope *parent_scope, AstNode * if (block_node->data.block.statements.length == 0) { if (scope_block->name != nullptr) { - add_node_error(irb->codegen, block_node, buf_sprintf("unused block label")); + add_node_error(ag->codegen, block_node, buf_sprintf("unused block label")); } // {} - return ir_lval_wrap(irb, parent_scope, ir_build_const_void(irb, child_scope, block_node), lval, result_loc); + return ir_lval_wrap(ag, parent_scope, ir_build_const_void(ag, child_scope, block_node), lval, result_loc); } if (block_node->data.block.name != nullptr) { scope_block->lval = lval; scope_block->incoming_blocks = &incoming_blocks; scope_block->incoming_values = &incoming_values; - scope_block->end_block = ir_create_basic_block(irb, parent_scope, "BlockEnd"); - scope_block->is_comptime = ir_build_const_bool(irb, parent_scope, block_node, - ir_should_inline(irb->exec, parent_scope)); + scope_block->end_block = ir_create_basic_block(ag, parent_scope, "BlockEnd"); + scope_block->is_comptime = ir_build_const_bool(ag, parent_scope, block_node, + ir_should_inline(ag->exec, parent_scope)); scope_block->peer_parent = heap::c_allocator.create(); scope_block->peer_parent->base.id = ResultLocIdPeerParent; @@ -3310,7 +3310,7 @@ static IrInstSrc *ir_gen_block(IrBuilderSrc *irb, Scope *parent_scope, AstNode * scope_block->peer_parent->end_bb = scope_block->end_block; scope_block->peer_parent->is_comptime = scope_block->is_comptime; scope_block->peer_parent->parent = result_loc; - ir_build_reset_result(irb, parent_scope, block_node, &scope_block->peer_parent->base); + ir_build_reset_result(ag, parent_scope, block_node, &scope_block->peer_parent->base); } bool is_continuation_unreachable = false; @@ -3319,8 +3319,8 @@ static IrInstSrc *ir_gen_block(IrBuilderSrc *irb, Scope *parent_scope, AstNode * for (size_t i = 0; i < block_node->data.block.statements.length; i += 1) { AstNode *statement_node = block_node->data.block.statements.at(i); - IrInstSrc *statement_value = ir_gen_node(irb, statement_node, child_scope); - if (statement_value == irb->codegen->invalid_inst_src) { + IrInstSrc *statement_value = ir_gen_node(ag, statement_node, child_scope); + if (statement_value == ag->codegen->invalid_inst_src) { // keep generating all the elements of the block in case of error, // we want to collect other compile errors found_invalid_inst = true; @@ -3344,16 +3344,16 @@ static IrInstSrc *ir_gen_block(IrBuilderSrc *irb, Scope *parent_scope, AstNode * child_scope = decl_var_instruction->var->child_scope; } else if (!is_continuation_unreachable) { // this statement's value must be void - ir_mark_gen(ir_build_check_statement_is_void(irb, child_scope, statement_node, statement_value)); + ir_mark_gen(ir_build_check_statement_is_void(ag, child_scope, statement_node, statement_value)); } } if (scope_block->name != nullptr && scope_block->name_used == false) { - add_node_error(irb->codegen, block_node, buf_sprintf("unused block label")); + add_node_error(ag->codegen, block_node, buf_sprintf("unused block label")); } if (found_invalid_inst) - return irb->codegen->invalid_inst_src; + return ag->codegen->invalid_inst_src; if (is_continuation_unreachable) { assert(noreturn_return_value != nullptr); @@ -3364,18 +3364,18 @@ static IrInstSrc *ir_gen_block(IrBuilderSrc *irb, Scope *parent_scope, AstNode * if (scope_block->peer_parent != nullptr && scope_block->peer_parent->peers.length != 0) { scope_block->peer_parent->peers.last()->next_bb = scope_block->end_block; } - ir_set_cursor_at_end_and_append_block(irb, scope_block->end_block); - IrInstSrc *phi = ir_build_phi(irb, parent_scope, block_node, incoming_blocks.length, + ir_set_cursor_at_end_and_append_block(ag, scope_block->end_block); + IrInstSrc *phi = ir_build_phi(ag, parent_scope, block_node, incoming_blocks.length, incoming_blocks.items, incoming_values.items, scope_block->peer_parent); - return ir_expr_wrap(irb, parent_scope, phi, result_loc); + return ir_expr_wrap(ag, parent_scope, phi, result_loc); } else { - incoming_blocks.append(irb->current_basic_block); - IrInstSrc *else_expr_result = ir_mark_gen(ir_build_const_void(irb, parent_scope, block_node)); + incoming_blocks.append(ag->current_basic_block); + IrInstSrc *else_expr_result = ir_mark_gen(ir_build_const_void(ag, parent_scope, block_node)); if (scope_block->peer_parent != nullptr) { ResultLocPeer *peer_result = create_peer_result(scope_block->peer_parent); scope_block->peer_parent->peers.append(peer_result); - ir_build_end_expr(irb, parent_scope, block_node, else_expr_result, &peer_result->base); + ir_build_end_expr(ag, parent_scope, block_node, else_expr_result, &peer_result->base); if (scope_block->peer_parent->peers.length != 0) { scope_block->peer_parent->peers.last()->next_bb = scope_block->end_block; @@ -3385,22 +3385,22 @@ static IrInstSrc *ir_gen_block(IrBuilderSrc *irb, Scope *parent_scope, AstNode * incoming_values.append(else_expr_result); } - bool is_return_from_fn = block_node == irb->main_block_node; + bool is_return_from_fn = block_node == ag->main_block_node; if (!is_return_from_fn) { - if (!ir_gen_defers_for_block(irb, child_scope, outer_block_scope, nullptr, nullptr)) - return irb->codegen->invalid_inst_src; + if (!ir_gen_defers_for_block(ag, child_scope, outer_block_scope, nullptr, nullptr)) + return ag->codegen->invalid_inst_src; } IrInstSrc *result; if (block_node->data.block.name != nullptr) { - ir_mark_gen(ir_build_br(irb, parent_scope, block_node, scope_block->end_block, scope_block->is_comptime)); - ir_set_cursor_at_end_and_append_block(irb, scope_block->end_block); - IrInstSrc *phi = ir_build_phi(irb, parent_scope, block_node, incoming_blocks.length, + ir_mark_gen(ir_build_br(ag, parent_scope, block_node, scope_block->end_block, scope_block->is_comptime)); + ir_set_cursor_at_end_and_append_block(ag, scope_block->end_block); + IrInstSrc *phi = ir_build_phi(ag, parent_scope, block_node, incoming_blocks.length, incoming_blocks.items, incoming_values.items, scope_block->peer_parent); - result = ir_expr_wrap(irb, parent_scope, phi, result_loc); + result = ir_expr_wrap(ag, parent_scope, phi, result_loc); } else { - IrInstSrc *void_inst = ir_mark_gen(ir_build_const_void(irb, child_scope, block_node)); - result = ir_lval_wrap(irb, parent_scope, void_inst, lval, result_loc); + IrInstSrc *void_inst = ir_mark_gen(ir_build_const_void(ag, child_scope, block_node)); + result = ir_lval_wrap(ag, parent_scope, void_inst, lval, result_loc); } if (!is_return_from_fn) return result; @@ -3408,108 +3408,108 @@ static IrInstSrc *ir_gen_block(IrBuilderSrc *irb, Scope *parent_scope, AstNode * // no need for save_err_ret_addr because this cannot return error // only generate unconditional defers - ir_mark_gen(ir_build_add_implicit_return_type(irb, child_scope, block_node, result, nullptr)); + ir_mark_gen(ir_build_add_implicit_return_type(ag, child_scope, block_node, result, nullptr)); ResultLocReturn *result_loc_ret = heap::c_allocator.create(); result_loc_ret->base.id = ResultLocIdReturn; - ir_build_reset_result(irb, parent_scope, block_node, &result_loc_ret->base); - ir_mark_gen(ir_build_end_expr(irb, parent_scope, block_node, result, &result_loc_ret->base)); - if (!ir_gen_defers_for_block(irb, child_scope, outer_block_scope, nullptr, nullptr)) - return irb->codegen->invalid_inst_src; - return ir_mark_gen(ir_build_return_src(irb, child_scope, result->base.source_node, result)); + ir_build_reset_result(ag, parent_scope, block_node, &result_loc_ret->base); + ir_mark_gen(ir_build_end_expr(ag, parent_scope, block_node, result, &result_loc_ret->base)); + if (!ir_gen_defers_for_block(ag, child_scope, outer_block_scope, nullptr, nullptr)) + return ag->codegen->invalid_inst_src; + return ir_mark_gen(ir_build_return_src(ag, child_scope, result->base.source_node, result)); } -static IrInstSrc *ir_gen_bin_op_id(IrBuilderSrc *irb, Scope *scope, AstNode *node, IrBinOp op_id) { +static IrInstSrc *ir_gen_bin_op_id(Stage1AstGen *ag, Scope *scope, AstNode *node, IrBinOp op_id) { Scope *inner_scope = scope; if (op_id == IrBinOpArrayCat || op_id == IrBinOpArrayMult) { - inner_scope = create_comptime_scope(irb->codegen, node, scope); + inner_scope = create_comptime_scope(ag->codegen, node, scope); } - IrInstSrc *op1 = ir_gen_node(irb, node->data.bin_op_expr.op1, inner_scope); - IrInstSrc *op2 = ir_gen_node(irb, node->data.bin_op_expr.op2, inner_scope); + IrInstSrc *op1 = ir_gen_node(ag, node->data.bin_op_expr.op1, inner_scope); + IrInstSrc *op2 = ir_gen_node(ag, node->data.bin_op_expr.op2, inner_scope); - if (op1 == irb->codegen->invalid_inst_src || op2 == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; + if (op1 == ag->codegen->invalid_inst_src || op2 == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; - return ir_build_bin_op(irb, scope, node, op_id, op1, op2, true); + return ir_build_bin_op(ag, scope, node, op_id, op1, op2, true); } -static IrInstSrc *ir_gen_merge_err_sets(IrBuilderSrc *irb, Scope *scope, AstNode *node) { - IrInstSrc *op1 = ir_gen_node(irb, node->data.bin_op_expr.op1, scope); - IrInstSrc *op2 = ir_gen_node(irb, node->data.bin_op_expr.op2, scope); +static IrInstSrc *ir_gen_merge_err_sets(Stage1AstGen *ag, Scope *scope, AstNode *node) { + IrInstSrc *op1 = ir_gen_node(ag, node->data.bin_op_expr.op1, scope); + IrInstSrc *op2 = ir_gen_node(ag, node->data.bin_op_expr.op2, scope); - if (op1 == irb->codegen->invalid_inst_src || op2 == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; + if (op1 == ag->codegen->invalid_inst_src || op2 == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; // TODO only pass type_name when the || operator is the top level AST node in the var decl expr Buf bare_name = BUF_INIT; - Buf *type_name = get_anon_type_name(irb->codegen, irb->exec, "error", scope, node, &bare_name); + Buf *type_name = get_anon_type_name(ag->codegen, ag->exec, "error", scope, node, &bare_name); - return ir_build_merge_err_sets(irb, scope, node, op1, op2, type_name); + return ir_build_merge_err_sets(ag, scope, node, op1, op2, type_name); } -static IrInstSrc *ir_gen_assign(IrBuilderSrc *irb, Scope *scope, AstNode *node) { - IrInstSrc *lvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op1, scope, LValAssign, nullptr); - if (lvalue == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; +static IrInstSrc *ir_gen_assign(Stage1AstGen *ag, Scope *scope, AstNode *node) { + IrInstSrc *lvalue = ir_gen_node_extra(ag, node->data.bin_op_expr.op1, scope, LValAssign, nullptr); + if (lvalue == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; ResultLocInstruction *result_loc_inst = heap::c_allocator.create(); result_loc_inst->base.id = ResultLocIdInstruction; result_loc_inst->base.source_instruction = lvalue; - ir_ref_instruction(lvalue, irb->current_basic_block); - ir_build_reset_result(irb, scope, node, &result_loc_inst->base); + ir_ref_instruction(lvalue, ag->current_basic_block); + ir_build_reset_result(ag, scope, node, &result_loc_inst->base); - IrInstSrc *rvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op2, scope, LValNone, + IrInstSrc *rvalue = ir_gen_node_extra(ag, node->data.bin_op_expr.op2, scope, LValNone, &result_loc_inst->base); - if (rvalue == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; + if (rvalue == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; - return ir_build_const_void(irb, scope, node); + return ir_build_const_void(ag, scope, node); } -static IrInstSrc *ir_gen_assign_op(IrBuilderSrc *irb, Scope *scope, AstNode *node, IrBinOp op_id) { - IrInstSrc *lvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op1, scope, LValAssign, nullptr); - if (lvalue == irb->codegen->invalid_inst_src) +static IrInstSrc *ir_gen_assign_op(Stage1AstGen *ag, Scope *scope, AstNode *node, IrBinOp op_id) { + IrInstSrc *lvalue = ir_gen_node_extra(ag, node->data.bin_op_expr.op1, scope, LValAssign, nullptr); + if (lvalue == ag->codegen->invalid_inst_src) return lvalue; - IrInstSrc *op1 = ir_build_load_ptr(irb, scope, node->data.bin_op_expr.op1, lvalue); - IrInstSrc *op2 = ir_gen_node(irb, node->data.bin_op_expr.op2, scope); - if (op2 == irb->codegen->invalid_inst_src) + IrInstSrc *op1 = ir_build_load_ptr(ag, scope, node->data.bin_op_expr.op1, lvalue); + IrInstSrc *op2 = ir_gen_node(ag, node->data.bin_op_expr.op2, scope); + if (op2 == ag->codegen->invalid_inst_src) return op2; - IrInstSrc *result = ir_build_bin_op(irb, scope, node, op_id, op1, op2, true); - ir_build_store_ptr(irb, scope, node, lvalue, result); - return ir_build_const_void(irb, scope, node); + IrInstSrc *result = ir_build_bin_op(ag, scope, node, op_id, op1, op2, true); + ir_build_store_ptr(ag, scope, node, lvalue, result); + return ir_build_const_void(ag, scope, node); } -static IrInstSrc *ir_gen_bool_or(IrBuilderSrc *irb, Scope *scope, AstNode *node) { +static IrInstSrc *ir_gen_bool_or(Stage1AstGen *ag, Scope *scope, AstNode *node) { assert(node->type == NodeTypeBinOpExpr); - IrInstSrc *val1 = ir_gen_node(irb, node->data.bin_op_expr.op1, scope); - if (val1 == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - IrBasicBlockSrc *post_val1_block = irb->current_basic_block; + IrInstSrc *val1 = ir_gen_node(ag, node->data.bin_op_expr.op1, scope); + if (val1 == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; + IrBasicBlockSrc *post_val1_block = ag->current_basic_block; IrInstSrc *is_comptime; - if (ir_should_inline(irb->exec, scope)) { - is_comptime = ir_build_const_bool(irb, scope, node, true); + if (ir_should_inline(ag->exec, scope)) { + is_comptime = ir_build_const_bool(ag, scope, node, true); } else { - is_comptime = ir_build_test_comptime(irb, scope, node, val1); + is_comptime = ir_build_test_comptime(ag, scope, node, val1); } // block for when val1 == false - IrBasicBlockSrc *false_block = ir_create_basic_block(irb, scope, "BoolOrFalse"); + IrBasicBlockSrc *false_block = ir_create_basic_block(ag, scope, "BoolOrFalse"); // block for when val1 == true (don't even evaluate the second part) - IrBasicBlockSrc *true_block = ir_create_basic_block(irb, scope, "BoolOrTrue"); + IrBasicBlockSrc *true_block = ir_create_basic_block(ag, scope, "BoolOrTrue"); - ir_build_cond_br(irb, scope, node, val1, true_block, false_block, is_comptime); + ir_build_cond_br(ag, scope, node, val1, true_block, false_block, is_comptime); - ir_set_cursor_at_end_and_append_block(irb, false_block); - IrInstSrc *val2 = ir_gen_node(irb, node->data.bin_op_expr.op2, scope); - if (val2 == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - IrBasicBlockSrc *post_val2_block = irb->current_basic_block; + ir_set_cursor_at_end_and_append_block(ag, false_block); + IrInstSrc *val2 = ir_gen_node(ag, node->data.bin_op_expr.op2, scope); + if (val2 == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; + IrBasicBlockSrc *post_val2_block = ag->current_basic_block; - ir_build_br(irb, scope, node, true_block, is_comptime); + ir_build_br(ag, scope, node, true_block, is_comptime); - ir_set_cursor_at_end_and_append_block(irb, true_block); + ir_set_cursor_at_end_and_append_block(ag, true_block); IrInstSrc **incoming_values = heap::c_allocator.allocate(2); incoming_values[0] = val1; @@ -3518,40 +3518,40 @@ static IrInstSrc *ir_gen_bool_or(IrBuilderSrc *irb, Scope *scope, AstNode *node) incoming_blocks[0] = post_val1_block; incoming_blocks[1] = post_val2_block; - return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, nullptr); + return ir_build_phi(ag, scope, node, 2, incoming_blocks, incoming_values, nullptr); } -static IrInstSrc *ir_gen_bool_and(IrBuilderSrc *irb, Scope *scope, AstNode *node) { +static IrInstSrc *ir_gen_bool_and(Stage1AstGen *ag, Scope *scope, AstNode *node) { assert(node->type == NodeTypeBinOpExpr); - IrInstSrc *val1 = ir_gen_node(irb, node->data.bin_op_expr.op1, scope); - if (val1 == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - IrBasicBlockSrc *post_val1_block = irb->current_basic_block; + IrInstSrc *val1 = ir_gen_node(ag, node->data.bin_op_expr.op1, scope); + if (val1 == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; + IrBasicBlockSrc *post_val1_block = ag->current_basic_block; IrInstSrc *is_comptime; - if (ir_should_inline(irb->exec, scope)) { - is_comptime = ir_build_const_bool(irb, scope, node, true); + if (ir_should_inline(ag->exec, scope)) { + is_comptime = ir_build_const_bool(ag, scope, node, true); } else { - is_comptime = ir_build_test_comptime(irb, scope, node, val1); + is_comptime = ir_build_test_comptime(ag, scope, node, val1); } // block for when val1 == true - IrBasicBlockSrc *true_block = ir_create_basic_block(irb, scope, "BoolAndTrue"); + IrBasicBlockSrc *true_block = ir_create_basic_block(ag, scope, "BoolAndTrue"); // block for when val1 == false (don't even evaluate the second part) - IrBasicBlockSrc *false_block = ir_create_basic_block(irb, scope, "BoolAndFalse"); + IrBasicBlockSrc *false_block = ir_create_basic_block(ag, scope, "BoolAndFalse"); - ir_build_cond_br(irb, scope, node, val1, true_block, false_block, is_comptime); + ir_build_cond_br(ag, scope, node, val1, true_block, false_block, is_comptime); - ir_set_cursor_at_end_and_append_block(irb, true_block); - IrInstSrc *val2 = ir_gen_node(irb, node->data.bin_op_expr.op2, scope); - if (val2 == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - IrBasicBlockSrc *post_val2_block = irb->current_basic_block; + ir_set_cursor_at_end_and_append_block(ag, true_block); + IrInstSrc *val2 = ir_gen_node(ag, node->data.bin_op_expr.op2, scope); + if (val2 == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; + IrBasicBlockSrc *post_val2_block = ag->current_basic_block; - ir_build_br(irb, scope, node, false_block, is_comptime); + ir_build_br(ag, scope, node, false_block, is_comptime); - ir_set_cursor_at_end_and_append_block(irb, false_block); + ir_set_cursor_at_end_and_append_block(ag, false_block); IrInstSrc **incoming_values = heap::c_allocator.allocate(2); incoming_values[0] = val1; @@ -3560,10 +3560,10 @@ static IrInstSrc *ir_gen_bool_and(IrBuilderSrc *irb, Scope *scope, AstNode *node incoming_blocks[0] = post_val1_block; incoming_blocks[1] = post_val2_block; - return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, nullptr); + return ir_build_phi(ag, scope, node, 2, incoming_blocks, incoming_values, nullptr); } -static ResultLocPeerParent *ir_build_result_peers(IrBuilderSrc *irb, IrInstSrc *cond_br_inst, +static ResultLocPeerParent *ir_build_result_peers(Stage1AstGen *ag, IrInstSrc *cond_br_inst, IrBasicBlockSrc *end_block, ResultLoc *parent, IrInstSrc *is_comptime) { ResultLocPeerParent *peer_parent = heap::c_allocator.create(); @@ -3574,19 +3574,19 @@ static ResultLocPeerParent *ir_build_result_peers(IrBuilderSrc *irb, IrInstSrc * peer_parent->is_comptime = is_comptime; peer_parent->parent = parent; - IrInstSrc *popped_inst = irb->current_basic_block->instruction_list.pop(); + IrInstSrc *popped_inst = ag->current_basic_block->instruction_list.pop(); ir_assert(popped_inst == cond_br_inst, &cond_br_inst->base); - ir_build_reset_result(irb, cond_br_inst->base.scope, cond_br_inst->base.source_node, &peer_parent->base); - irb->current_basic_block->instruction_list.append(popped_inst); + ir_build_reset_result(ag, cond_br_inst->base.scope, cond_br_inst->base.source_node, &peer_parent->base); + ag->current_basic_block->instruction_list.append(popped_inst); return peer_parent; } -static ResultLocPeerParent *ir_build_binary_result_peers(IrBuilderSrc *irb, IrInstSrc *cond_br_inst, +static ResultLocPeerParent *ir_build_binary_result_peers(Stage1AstGen *ag, IrInstSrc *cond_br_inst, IrBasicBlockSrc *else_block, IrBasicBlockSrc *end_block, ResultLoc *parent, IrInstSrc *is_comptime) { - ResultLocPeerParent *peer_parent = ir_build_result_peers(irb, cond_br_inst, end_block, parent, is_comptime); + ResultLocPeerParent *peer_parent = ir_build_result_peers(ag, cond_br_inst, end_block, parent, is_comptime); peer_parent->peers.append(create_peer_result(peer_parent)); peer_parent->peers.last()->next_bb = else_block; @@ -3597,7 +3597,7 @@ static ResultLocPeerParent *ir_build_binary_result_peers(IrBuilderSrc *irb, IrIn return peer_parent; } -static IrInstSrc *ir_gen_orelse(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node, LVal lval, +static IrInstSrc *ir_gen_orelse(Stage1AstGen *ag, Scope *parent_scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypeBinOpExpr); @@ -3605,73 +3605,73 @@ static IrInstSrc *ir_gen_orelse(IrBuilderSrc *irb, Scope *parent_scope, AstNode AstNode *op1_node = node->data.bin_op_expr.op1; AstNode *op2_node = node->data.bin_op_expr.op2; - IrInstSrc *maybe_ptr = ir_gen_node_extra(irb, op1_node, parent_scope, LValPtr, nullptr); - if (maybe_ptr == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; + IrInstSrc *maybe_ptr = ir_gen_node_extra(ag, op1_node, parent_scope, LValPtr, nullptr); + if (maybe_ptr == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; - IrInstSrc *maybe_val = ir_build_load_ptr(irb, parent_scope, node, maybe_ptr); - IrInstSrc *is_non_null = ir_build_test_non_null_src(irb, parent_scope, node, maybe_val); + IrInstSrc *maybe_val = ir_build_load_ptr(ag, parent_scope, node, maybe_ptr); + IrInstSrc *is_non_null = ir_build_test_non_null_src(ag, parent_scope, node, maybe_val); IrInstSrc *is_comptime; - if (ir_should_inline(irb->exec, parent_scope)) { - is_comptime = ir_build_const_bool(irb, parent_scope, node, true); + if (ir_should_inline(ag->exec, parent_scope)) { + is_comptime = ir_build_const_bool(ag, parent_scope, node, true); } else { - is_comptime = ir_build_test_comptime(irb, parent_scope, node, is_non_null); + is_comptime = ir_build_test_comptime(ag, parent_scope, node, is_non_null); } - IrBasicBlockSrc *ok_block = ir_create_basic_block(irb, parent_scope, "OptionalNonNull"); - IrBasicBlockSrc *null_block = ir_create_basic_block(irb, parent_scope, "OptionalNull"); - IrBasicBlockSrc *end_block = ir_create_basic_block(irb, parent_scope, "OptionalEnd"); - IrInstSrc *cond_br_inst = ir_build_cond_br(irb, parent_scope, node, is_non_null, ok_block, null_block, is_comptime); + IrBasicBlockSrc *ok_block = ir_create_basic_block(ag, parent_scope, "OptionalNonNull"); + IrBasicBlockSrc *null_block = ir_create_basic_block(ag, parent_scope, "OptionalNull"); + IrBasicBlockSrc *end_block = ir_create_basic_block(ag, parent_scope, "OptionalEnd"); + IrInstSrc *cond_br_inst = ir_build_cond_br(ag, parent_scope, node, is_non_null, ok_block, null_block, is_comptime); - ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, ok_block, end_block, + ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(ag, cond_br_inst, ok_block, end_block, result_loc, is_comptime); - ir_set_cursor_at_end_and_append_block(irb, null_block); - IrInstSrc *null_result = ir_gen_node_extra(irb, op2_node, parent_scope, LValNone, + ir_set_cursor_at_end_and_append_block(ag, null_block); + IrInstSrc *null_result = ir_gen_node_extra(ag, op2_node, parent_scope, LValNone, &peer_parent->peers.at(0)->base); - if (null_result == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - IrBasicBlockSrc *after_null_block = irb->current_basic_block; + if (null_result == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; + IrBasicBlockSrc *after_null_block = ag->current_basic_block; if (!instr_is_unreachable(null_result)) - ir_mark_gen(ir_build_br(irb, parent_scope, node, end_block, is_comptime)); + ir_mark_gen(ir_build_br(ag, parent_scope, node, end_block, is_comptime)); - ir_set_cursor_at_end_and_append_block(irb, ok_block); - IrInstSrc *unwrapped_ptr = ir_build_optional_unwrap_ptr(irb, parent_scope, node, maybe_ptr, false); - IrInstSrc *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr); - ir_build_end_expr(irb, parent_scope, node, unwrapped_payload, &peer_parent->peers.at(1)->base); - IrBasicBlockSrc *after_ok_block = irb->current_basic_block; - ir_build_br(irb, parent_scope, node, end_block, is_comptime); + ir_set_cursor_at_end_and_append_block(ag, ok_block); + IrInstSrc *unwrapped_ptr = ir_build_optional_unwrap_ptr(ag, parent_scope, node, maybe_ptr, false); + IrInstSrc *unwrapped_payload = ir_build_load_ptr(ag, parent_scope, node, unwrapped_ptr); + ir_build_end_expr(ag, parent_scope, node, unwrapped_payload, &peer_parent->peers.at(1)->base); + IrBasicBlockSrc *after_ok_block = ag->current_basic_block; + ir_build_br(ag, parent_scope, node, end_block, is_comptime); - ir_set_cursor_at_end_and_append_block(irb, end_block); + ir_set_cursor_at_end_and_append_block(ag, end_block); IrInstSrc **incoming_values = heap::c_allocator.allocate(2); incoming_values[0] = null_result; incoming_values[1] = unwrapped_payload; IrBasicBlockSrc **incoming_blocks = heap::c_allocator.allocate(2); incoming_blocks[0] = after_null_block; incoming_blocks[1] = after_ok_block; - IrInstSrc *phi = ir_build_phi(irb, parent_scope, node, 2, incoming_blocks, incoming_values, peer_parent); - return ir_lval_wrap(irb, parent_scope, phi, lval, result_loc); + IrInstSrc *phi = ir_build_phi(ag, parent_scope, node, 2, incoming_blocks, incoming_values, peer_parent); + return ir_lval_wrap(ag, parent_scope, phi, lval, result_loc); } -static IrInstSrc *ir_gen_error_union(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node) { +static IrInstSrc *ir_gen_error_union(Stage1AstGen *ag, Scope *parent_scope, AstNode *node) { assert(node->type == NodeTypeBinOpExpr); AstNode *op1_node = node->data.bin_op_expr.op1; AstNode *op2_node = node->data.bin_op_expr.op2; - IrInstSrc *err_set = ir_gen_node(irb, op1_node, parent_scope); - if (err_set == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; + IrInstSrc *err_set = ir_gen_node(ag, op1_node, parent_scope); + if (err_set == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; - IrInstSrc *payload = ir_gen_node(irb, op2_node, parent_scope); - if (payload == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; + IrInstSrc *payload = ir_gen_node(ag, op2_node, parent_scope); + if (payload == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; - return ir_build_error_union(irb, parent_scope, node, err_set, payload); + return ir_build_error_union(ag, parent_scope, node, err_set, payload); } -static IrInstSrc *ir_gen_bin_op(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { +static IrInstSrc *ir_gen_bin_op(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypeBinOpExpr); BinOpType bin_op_type = node->data.bin_op_expr.bin_op; @@ -3679,99 +3679,99 @@ static IrInstSrc *ir_gen_bin_op(IrBuilderSrc *irb, Scope *scope, AstNode *node, case BinOpTypeInvalid: zig_unreachable(); case BinOpTypeAssign: - return ir_lval_wrap(irb, scope, ir_gen_assign(irb, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_assign(ag, scope, node), lval, result_loc); case BinOpTypeAssignTimes: - return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpMult), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_assign_op(ag, scope, node, IrBinOpMult), lval, result_loc); case BinOpTypeAssignTimesWrap: - return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpMultWrap), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_assign_op(ag, scope, node, IrBinOpMultWrap), lval, result_loc); case BinOpTypeAssignDiv: - return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpDivUnspecified), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_assign_op(ag, scope, node, IrBinOpDivUnspecified), lval, result_loc); case BinOpTypeAssignMod: - return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpRemUnspecified), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_assign_op(ag, scope, node, IrBinOpRemUnspecified), lval, result_loc); case BinOpTypeAssignPlus: - return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpAdd), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_assign_op(ag, scope, node, IrBinOpAdd), lval, result_loc); case BinOpTypeAssignPlusWrap: - return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpAddWrap), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_assign_op(ag, scope, node, IrBinOpAddWrap), lval, result_loc); case BinOpTypeAssignMinus: - return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpSub), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_assign_op(ag, scope, node, IrBinOpSub), lval, result_loc); case BinOpTypeAssignMinusWrap: - return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpSubWrap), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_assign_op(ag, scope, node, IrBinOpSubWrap), lval, result_loc); case BinOpTypeAssignBitShiftLeft: - return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpBitShiftLeftLossy), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_assign_op(ag, scope, node, IrBinOpBitShiftLeftLossy), lval, result_loc); case BinOpTypeAssignBitShiftRight: - return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpBitShiftRightLossy), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_assign_op(ag, scope, node, IrBinOpBitShiftRightLossy), lval, result_loc); case BinOpTypeAssignBitAnd: - return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpBinAnd), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_assign_op(ag, scope, node, IrBinOpBinAnd), lval, result_loc); case BinOpTypeAssignBitXor: - return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpBinXor), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_assign_op(ag, scope, node, IrBinOpBinXor), lval, result_loc); case BinOpTypeAssignBitOr: - return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpBinOr), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_assign_op(ag, scope, node, IrBinOpBinOr), lval, result_loc); case BinOpTypeBoolOr: - return ir_lval_wrap(irb, scope, ir_gen_bool_or(irb, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_bool_or(ag, scope, node), lval, result_loc); case BinOpTypeBoolAnd: - return ir_lval_wrap(irb, scope, ir_gen_bool_and(irb, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_bool_and(ag, scope, node), lval, result_loc); case BinOpTypeCmpEq: - return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpEq), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_bin_op_id(ag, scope, node, IrBinOpCmpEq), lval, result_loc); case BinOpTypeCmpNotEq: - return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpNotEq), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_bin_op_id(ag, scope, node, IrBinOpCmpNotEq), lval, result_loc); case BinOpTypeCmpLessThan: - return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpLessThan), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_bin_op_id(ag, scope, node, IrBinOpCmpLessThan), lval, result_loc); case BinOpTypeCmpGreaterThan: - return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpGreaterThan), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_bin_op_id(ag, scope, node, IrBinOpCmpGreaterThan), lval, result_loc); case BinOpTypeCmpLessOrEq: - return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpLessOrEq), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_bin_op_id(ag, scope, node, IrBinOpCmpLessOrEq), lval, result_loc); case BinOpTypeCmpGreaterOrEq: - return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpGreaterOrEq), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_bin_op_id(ag, scope, node, IrBinOpCmpGreaterOrEq), lval, result_loc); case BinOpTypeBinOr: - return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpBinOr), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_bin_op_id(ag, scope, node, IrBinOpBinOr), lval, result_loc); case BinOpTypeBinXor: - return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpBinXor), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_bin_op_id(ag, scope, node, IrBinOpBinXor), lval, result_loc); case BinOpTypeBinAnd: - return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpBinAnd), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_bin_op_id(ag, scope, node, IrBinOpBinAnd), lval, result_loc); case BinOpTypeBitShiftLeft: - return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpBitShiftLeftLossy), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_bin_op_id(ag, scope, node, IrBinOpBitShiftLeftLossy), lval, result_loc); case BinOpTypeBitShiftRight: - return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpBitShiftRightLossy), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_bin_op_id(ag, scope, node, IrBinOpBitShiftRightLossy), lval, result_loc); case BinOpTypeAdd: - return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpAdd), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_bin_op_id(ag, scope, node, IrBinOpAdd), lval, result_loc); case BinOpTypeAddWrap: - return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpAddWrap), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_bin_op_id(ag, scope, node, IrBinOpAddWrap), lval, result_loc); case BinOpTypeSub: - return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpSub), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_bin_op_id(ag, scope, node, IrBinOpSub), lval, result_loc); case BinOpTypeSubWrap: - return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpSubWrap), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_bin_op_id(ag, scope, node, IrBinOpSubWrap), lval, result_loc); case BinOpTypeMult: - return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpMult), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_bin_op_id(ag, scope, node, IrBinOpMult), lval, result_loc); case BinOpTypeMultWrap: - return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpMultWrap), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_bin_op_id(ag, scope, node, IrBinOpMultWrap), lval, result_loc); case BinOpTypeDiv: - return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpDivUnspecified), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_bin_op_id(ag, scope, node, IrBinOpDivUnspecified), lval, result_loc); case BinOpTypeMod: - return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpRemUnspecified), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_bin_op_id(ag, scope, node, IrBinOpRemUnspecified), lval, result_loc); case BinOpTypeArrayCat: - return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpArrayCat), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_bin_op_id(ag, scope, node, IrBinOpArrayCat), lval, result_loc); case BinOpTypeArrayMult: - return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpArrayMult), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_bin_op_id(ag, scope, node, IrBinOpArrayMult), lval, result_loc); case BinOpTypeMergeErrorSets: - return ir_lval_wrap(irb, scope, ir_gen_merge_err_sets(irb, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_merge_err_sets(ag, scope, node), lval, result_loc); case BinOpTypeUnwrapOptional: - return ir_gen_orelse(irb, scope, node, lval, result_loc); + return ir_gen_orelse(ag, scope, node, lval, result_loc); case BinOpTypeErrorUnion: - return ir_lval_wrap(irb, scope, ir_gen_error_union(irb, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_error_union(ag, scope, node), lval, result_loc); } zig_unreachable(); } -static IrInstSrc *ir_gen_int_lit(IrBuilderSrc *irb, Scope *scope, AstNode *node) { +static IrInstSrc *ir_gen_int_lit(Stage1AstGen *ag, Scope *scope, AstNode *node) { assert(node->type == NodeTypeIntLiteral); RootStruct *root_struct = node->owner->data.structure.root_struct; BigInt bigint; token_number_literal_bigint(root_struct, &bigint, node->main_token); - return ir_build_const_bigint(irb, scope, node, bigint); + return ir_build_const_bigint(ag, scope, node, bigint); } -static IrInstSrc *ir_gen_float_lit(IrBuilderSrc *irb, Scope *scope, AstNode *node) { +static IrInstSrc *ir_gen_float_lit(Stage1AstGen *ag, Scope *scope, AstNode *node) { Error err; assert(node->type == NodeTypeFloatLiteral); @@ -3781,14 +3781,14 @@ static IrInstSrc *ir_gen_float_lit(IrBuilderSrc *irb, Scope *scope, AstNode *nod BigFloat bigfloat; if ((err = bigfloat_init_buf(&bigfloat, (const uint8_t *)source + byte_offset))) { - add_node_error(irb->codegen, node, buf_sprintf("float literal out of range of any type")); - return irb->codegen->invalid_inst_src; + add_node_error(ag->codegen, node, buf_sprintf("float literal out of range of any type")); + return ag->codegen->invalid_inst_src; } - return ir_build_const_bigfloat(irb, scope, node, bigfloat); + return ir_build_const_bigfloat(ag, scope, node, bigfloat); } -static IrInstSrc *ir_gen_char_lit(IrBuilderSrc *irb, Scope *scope, AstNode *node) { +static IrInstSrc *ir_gen_char_lit(Stage1AstGen *ag, Scope *scope, AstNode *node) { Error err; assert(node->type == NodeTypeCharLiteral); @@ -3802,19 +3802,19 @@ static IrInstSrc *ir_gen_char_lit(IrBuilderSrc *irb, Scope *scope, AstNode *node uint32_t codepoint; size_t bad_index; if ((err = source_char_literal(source + byte_offset, &codepoint, &bad_index))) { - add_node_error(irb->codegen, node, buf_sprintf("invalid character")); - return irb->codegen->invalid_inst_src; + add_node_error(ag->codegen, node, buf_sprintf("invalid character")); + return ag->codegen->invalid_inst_src; } - return ir_build_const_uint(irb, scope, node, codepoint); + return ir_build_const_uint(ag, scope, node, codepoint); } -static IrInstSrc *ir_gen_null_literal(IrBuilderSrc *irb, Scope *scope, AstNode *node) { +static IrInstSrc *ir_gen_null_literal(Stage1AstGen *ag, Scope *scope, AstNode *node) { assert(node->type == NodeTypeNullLiteral); - return ir_build_const_null(irb, scope, node); + return ir_build_const_null(ag, scope, node); } -static IrInstSrc *ir_gen_symbol(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { +static IrInstSrc *ir_gen_symbol(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { Error err; assert(node->type == NodeTypeIdentifier); @@ -3822,113 +3822,113 @@ static IrInstSrc *ir_gen_symbol(IrBuilderSrc *irb, Scope *scope, AstNode *node, if (buf_eql_str(variable_name, "_")) { if (lval == LValAssign) { - IrInstSrcConst *const_instruction = ir_build_instruction(irb, scope, node); - const_instruction->value = irb->codegen->pass1_arena->create(); - const_instruction->value->type = get_pointer_to_type(irb->codegen, - irb->codegen->builtin_types.entry_void, false); + IrInstSrcConst *const_instruction = ir_build_instruction(ag, scope, node); + const_instruction->value = ag->codegen->pass1_arena->create(); + const_instruction->value->type = get_pointer_to_type(ag->codegen, + ag->codegen->builtin_types.entry_void, false); const_instruction->value->special = ConstValSpecialStatic; const_instruction->value->data.x_ptr.special = ConstPtrSpecialDiscard; return &const_instruction->base; } else { - add_node_error(irb->codegen, node, buf_sprintf("`_` may only be used to assign things to")); - return irb->codegen->invalid_inst_src; + add_node_error(ag->codegen, node, buf_sprintf("`_` may only be used to assign things to")); + return ag->codegen->invalid_inst_src; } } ZigType *primitive_type; - if ((err = get_primitive_type(irb->codegen, variable_name, &primitive_type))) { + if ((err = get_primitive_type(ag->codegen, variable_name, &primitive_type))) { if (err == ErrorOverflow) { - add_node_error(irb->codegen, node, + add_node_error(ag->codegen, node, buf_sprintf("primitive integer type '%s' exceeds maximum bit width of 65535", buf_ptr(variable_name))); - return irb->codegen->invalid_inst_src; + return ag->codegen->invalid_inst_src; } assert(err == ErrorPrimitiveTypeNotFound); } else { - IrInstSrc *value = ir_build_const_type(irb, scope, node, primitive_type); + IrInstSrc *value = ir_build_const_type(ag, scope, node, primitive_type); if (lval == LValPtr || lval == LValAssign) { - return ir_build_ref_src(irb, scope, node, value); + return ir_build_ref_src(ag, scope, node, value); } else { - return ir_expr_wrap(irb, scope, value, result_loc); + return ir_expr_wrap(ag, scope, value, result_loc); } } ScopeFnDef *crossed_fndef_scope; - ZigVar *var = find_variable(irb->codegen, scope, variable_name, &crossed_fndef_scope); + ZigVar *var = find_variable(ag->codegen, scope, variable_name, &crossed_fndef_scope); if (var) { - IrInstSrc *var_ptr = ir_build_var_ptr_x(irb, scope, node, var, crossed_fndef_scope); + IrInstSrc *var_ptr = ir_build_var_ptr_x(ag, scope, node, var, crossed_fndef_scope); if (lval == LValPtr || lval == LValAssign) { return var_ptr; } else { - return ir_expr_wrap(irb, scope, ir_build_load_ptr(irb, scope, node, var_ptr), result_loc); + return ir_expr_wrap(ag, scope, ir_build_load_ptr(ag, scope, node, var_ptr), result_loc); } } - Tld *tld = find_decl(irb->codegen, scope, variable_name); + Tld *tld = find_decl(ag->codegen, scope, variable_name); if (tld) { - IrInstSrc *decl_ref = ir_build_decl_ref(irb, scope, node, tld, lval); + IrInstSrc *decl_ref = ir_build_decl_ref(ag, scope, node, tld, lval); if (lval == LValPtr || lval == LValAssign) { return decl_ref; } else { - return ir_expr_wrap(irb, scope, decl_ref, result_loc); + return ir_expr_wrap(ag, scope, decl_ref, result_loc); } } if (get_container_scope(node->owner)->any_imports_failed) { // skip the error message since we had a failing import in this file // if an import breaks we don't need redundant undeclared identifier errors - return irb->codegen->invalid_inst_src; + return ag->codegen->invalid_inst_src; } - return ir_build_undeclared_identifier(irb, scope, node, variable_name); + return ir_build_undeclared_identifier(ag, scope, node, variable_name); } -static IrInstSrc *ir_gen_array_access(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, +static IrInstSrc *ir_gen_array_access(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypeArrayAccessExpr); AstNode *array_ref_node = node->data.array_access_expr.array_ref_expr; - IrInstSrc *array_ref_instruction = ir_gen_node_extra(irb, array_ref_node, scope, LValPtr, nullptr); - if (array_ref_instruction == irb->codegen->invalid_inst_src) + IrInstSrc *array_ref_instruction = ir_gen_node_extra(ag, array_ref_node, scope, LValPtr, nullptr); + if (array_ref_instruction == ag->codegen->invalid_inst_src) return array_ref_instruction; // Create an usize-typed result location to hold the subscript value, this // makes it possible for the compiler to infer the subscript expression type // if needed - IrInstSrc *usize_type_inst = ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_usize); - ResultLocCast *result_loc_cast = ir_build_cast_result_loc(irb, usize_type_inst, no_result_loc()); + IrInstSrc *usize_type_inst = ir_build_const_type(ag, scope, node, ag->codegen->builtin_types.entry_usize); + ResultLocCast *result_loc_cast = ir_build_cast_result_loc(ag, usize_type_inst, no_result_loc()); AstNode *subscript_node = node->data.array_access_expr.subscript; - IrInstSrc *subscript_value = ir_gen_node_extra(irb, subscript_node, scope, LValNone, &result_loc_cast->base); - if (subscript_value == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; + IrInstSrc *subscript_value = ir_gen_node_extra(ag, subscript_node, scope, LValNone, &result_loc_cast->base); + if (subscript_value == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; - IrInstSrc *subscript_instruction = ir_build_implicit_cast(irb, scope, subscript_node, subscript_value, result_loc_cast); + IrInstSrc *subscript_instruction = ir_build_implicit_cast(ag, scope, subscript_node, subscript_value, result_loc_cast); - IrInstSrc *ptr_instruction = ir_build_elem_ptr(irb, scope, node, array_ref_instruction, + IrInstSrc *ptr_instruction = ir_build_elem_ptr(ag, scope, node, array_ref_instruction, subscript_instruction, true, PtrLenSingle, nullptr); if (lval == LValPtr || lval == LValAssign) return ptr_instruction; - IrInstSrc *load_ptr = ir_build_load_ptr(irb, scope, node, ptr_instruction); - return ir_expr_wrap(irb, scope, load_ptr, result_loc); + IrInstSrc *load_ptr = ir_build_load_ptr(ag, scope, node, ptr_instruction); + return ir_expr_wrap(ag, scope, load_ptr, result_loc); } -static IrInstSrc *ir_gen_field_access(IrBuilderSrc *irb, Scope *scope, AstNode *node) { +static IrInstSrc *ir_gen_field_access(Stage1AstGen *ag, Scope *scope, AstNode *node) { assert(node->type == NodeTypeFieldAccessExpr); AstNode *container_ref_node = node->data.field_access_expr.struct_expr; Buf *field_name = node->data.field_access_expr.field_name; - IrInstSrc *container_ref_instruction = ir_gen_node_extra(irb, container_ref_node, scope, LValPtr, nullptr); - if (container_ref_instruction == irb->codegen->invalid_inst_src) + IrInstSrc *container_ref_instruction = ir_gen_node_extra(ag, container_ref_node, scope, LValPtr, nullptr); + if (container_ref_instruction == ag->codegen->invalid_inst_src) return container_ref_instruction; - return ir_build_field_ptr(irb, scope, node, container_ref_instruction, field_name, false); + return ir_build_field_ptr(ag, scope, node, container_ref_instruction, field_name, false); } -static IrInstSrc *ir_gen_overflow_op(IrBuilderSrc *irb, Scope *scope, AstNode *node, IrOverflowOp op) { +static IrInstSrc *ir_gen_overflow_op(Stage1AstGen *ag, Scope *scope, AstNode *node, IrOverflowOp op) { assert(node->type == NodeTypeFnCallExpr); AstNode *type_node = node->data.fn_call_expr.params.at(0); @@ -3937,26 +3937,26 @@ static IrInstSrc *ir_gen_overflow_op(IrBuilderSrc *irb, Scope *scope, AstNode *n AstNode *result_ptr_node = node->data.fn_call_expr.params.at(3); - IrInstSrc *type_value = ir_gen_node(irb, type_node, scope); - if (type_value == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; + IrInstSrc *type_value = ir_gen_node(ag, type_node, scope); + if (type_value == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; - IrInstSrc *op1 = ir_gen_node(irb, op1_node, scope); - if (op1 == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; + IrInstSrc *op1 = ir_gen_node(ag, op1_node, scope); + if (op1 == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; - IrInstSrc *op2 = ir_gen_node(irb, op2_node, scope); - if (op2 == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; + IrInstSrc *op2 = ir_gen_node(ag, op2_node, scope); + if (op2 == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; - IrInstSrc *result_ptr = ir_gen_node(irb, result_ptr_node, scope); - if (result_ptr == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; + IrInstSrc *result_ptr = ir_gen_node(ag, result_ptr_node, scope); + if (result_ptr == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; - return ir_build_overflow_op_src(irb, scope, node, op, type_value, op1, op2, result_ptr); + return ir_build_overflow_op_src(ag, scope, node, op, type_value, op1, op2, result_ptr); } -static IrInstSrc *ir_gen_mul_add(IrBuilderSrc *irb, Scope *scope, AstNode *node) { +static IrInstSrc *ir_gen_mul_add(Stage1AstGen *ag, Scope *scope, AstNode *node) { assert(node->type == NodeTypeFnCallExpr); AstNode *type_node = node->data.fn_call_expr.params.at(0); @@ -3964,63 +3964,63 @@ static IrInstSrc *ir_gen_mul_add(IrBuilderSrc *irb, Scope *scope, AstNode *node) AstNode *op2_node = node->data.fn_call_expr.params.at(2); AstNode *op3_node = node->data.fn_call_expr.params.at(3); - IrInstSrc *type_value = ir_gen_node(irb, type_node, scope); - if (type_value == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; + IrInstSrc *type_value = ir_gen_node(ag, type_node, scope); + if (type_value == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; - IrInstSrc *op1 = ir_gen_node(irb, op1_node, scope); - if (op1 == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; + IrInstSrc *op1 = ir_gen_node(ag, op1_node, scope); + if (op1 == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; - IrInstSrc *op2 = ir_gen_node(irb, op2_node, scope); - if (op2 == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; + IrInstSrc *op2 = ir_gen_node(ag, op2_node, scope); + if (op2 == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; - IrInstSrc *op3 = ir_gen_node(irb, op3_node, scope); - if (op3 == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; + IrInstSrc *op3 = ir_gen_node(ag, op3_node, scope); + if (op3 == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; - return ir_build_mul_add_src(irb, scope, node, type_value, op1, op2, op3); + return ir_build_mul_add_src(ag, scope, node, type_value, op1, op2, op3); } -static IrInstSrc *ir_gen_this(IrBuilderSrc *irb, Scope *orig_scope, AstNode *node) { +static IrInstSrc *ir_gen_this(Stage1AstGen *ag, Scope *orig_scope, AstNode *node) { for (Scope *it_scope = orig_scope; it_scope != nullptr; it_scope = it_scope->parent) { if (it_scope->id == ScopeIdDecls) { ScopeDecls *decls_scope = (ScopeDecls *)it_scope; ZigType *container_type = decls_scope->container_type; if (container_type != nullptr) { - return ir_build_const_type(irb, orig_scope, node, container_type); + return ir_build_const_type(ag, orig_scope, node, container_type); } else { - return ir_build_const_import(irb, orig_scope, node, decls_scope->import); + return ir_build_const_import(ag, orig_scope, node, decls_scope->import); } } } zig_unreachable(); } -static IrInstSrc *ir_gen_async_call(IrBuilderSrc *irb, Scope *scope, AstNode *await_node, AstNode *call_node, +static IrInstSrc *ir_gen_async_call(Stage1AstGen *ag, Scope *scope, AstNode *await_node, AstNode *call_node, LVal lval, ResultLoc *result_loc) { if (call_node->data.fn_call_expr.params.length != 4) { - add_node_error(irb->codegen, call_node, + add_node_error(ag->codegen, call_node, buf_sprintf("expected 4 arguments, found %" ZIG_PRI_usize, call_node->data.fn_call_expr.params.length)); - return irb->codegen->invalid_inst_src; + return ag->codegen->invalid_inst_src; } AstNode *bytes_node = call_node->data.fn_call_expr.params.at(0); - IrInstSrc *bytes = ir_gen_node(irb, bytes_node, scope); - if (bytes == irb->codegen->invalid_inst_src) + IrInstSrc *bytes = ir_gen_node(ag, bytes_node, scope); + if (bytes == ag->codegen->invalid_inst_src) return bytes; AstNode *ret_ptr_node = call_node->data.fn_call_expr.params.at(1); - IrInstSrc *ret_ptr = ir_gen_node(irb, ret_ptr_node, scope); - if (ret_ptr == irb->codegen->invalid_inst_src) + IrInstSrc *ret_ptr = ir_gen_node(ag, ret_ptr_node, scope); + if (ret_ptr == ag->codegen->invalid_inst_src) return ret_ptr; AstNode *fn_ref_node = call_node->data.fn_call_expr.params.at(2); - IrInstSrc *fn_ref = ir_gen_node(irb, fn_ref_node, scope); - if (fn_ref == irb->codegen->invalid_inst_src) + IrInstSrc *fn_ref = ir_gen_node(ag, fn_ref_node, scope); + if (fn_ref == ag->codegen->invalid_inst_src) return fn_ref; CallModifier modifier = (await_node == nullptr) ? CallModifierAsync : CallModifierNone; @@ -4034,89 +4034,89 @@ static IrInstSrc *ir_gen_async_call(IrBuilderSrc *irb, Scope *scope, AstNode *aw IrInstSrc **args = heap::c_allocator.allocate(arg_count); for (size_t i = 0; i < arg_count; i += 1) { AstNode *arg_node = args_node->data.container_init_expr.entries.at(i); - IrInstSrc *arg = ir_gen_node(irb, arg_node, scope); - if (arg == irb->codegen->invalid_inst_src) + IrInstSrc *arg = ir_gen_node(ag, arg_node, scope); + if (arg == ag->codegen->invalid_inst_src) return arg; args[i] = arg; } - IrInstSrc *call = ir_build_call_src(irb, scope, call_node, nullptr, fn_ref, arg_count, args, + IrInstSrc *call = ir_build_call_src(ag, scope, call_node, nullptr, fn_ref, arg_count, args, ret_ptr, modifier, is_async_call_builtin, bytes, result_loc); - return ir_lval_wrap(irb, scope, call, lval, result_loc); + return ir_lval_wrap(ag, scope, call, lval, result_loc); } else { - exec_add_error_node(irb->codegen, irb->exec, args_node, + exec_add_error_node(ag->codegen, ag->exec, args_node, buf_sprintf("TODO: @asyncCall with anon struct literal")); - return irb->codegen->invalid_inst_src; + return ag->codegen->invalid_inst_src; } } - IrInstSrc *args = ir_gen_node(irb, args_node, scope); - if (args == irb->codegen->invalid_inst_src) + IrInstSrc *args = ir_gen_node(ag, args_node, scope); + if (args == ag->codegen->invalid_inst_src) return args; - IrInstSrc *call = ir_build_async_call_extra(irb, scope, call_node, modifier, fn_ref, ret_ptr, bytes, args, result_loc); - return ir_lval_wrap(irb, scope, call, lval, result_loc); + IrInstSrc *call = ir_build_async_call_extra(ag, scope, call_node, modifier, fn_ref, ret_ptr, bytes, args, result_loc); + return ir_lval_wrap(ag, scope, call, lval, result_loc); } -static IrInstSrc *ir_gen_fn_call_with_args(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_gen_fn_call_with_args(Stage1AstGen *ag, Scope *scope, AstNode *source_node, AstNode *fn_ref_node, CallModifier modifier, IrInstSrc *options, AstNode **args_ptr, size_t args_len, LVal lval, ResultLoc *result_loc) { - IrInstSrc *fn_ref = ir_gen_node(irb, fn_ref_node, scope); - if (fn_ref == irb->codegen->invalid_inst_src) + IrInstSrc *fn_ref = ir_gen_node(ag, fn_ref_node, scope); + if (fn_ref == ag->codegen->invalid_inst_src) return fn_ref; - IrInstSrc *fn_type = ir_build_typeof_1(irb, scope, source_node, fn_ref); + IrInstSrc *fn_type = ir_build_typeof_1(ag, scope, source_node, fn_ref); IrInstSrc **args = heap::c_allocator.allocate(args_len); for (size_t i = 0; i < args_len; i += 1) { AstNode *arg_node = args_ptr[i]; - IrInstSrc *arg_index = ir_build_const_usize(irb, scope, arg_node, i); - IrInstSrc *arg_type = ir_build_arg_type(irb, scope, source_node, fn_type, arg_index, true); + IrInstSrc *arg_index = ir_build_const_usize(ag, scope, arg_node, i); + IrInstSrc *arg_type = ir_build_arg_type(ag, scope, source_node, fn_type, arg_index, true); ResultLoc *no_result = no_result_loc(); - ir_build_reset_result(irb, scope, source_node, no_result); - ResultLocCast *result_loc_cast = ir_build_cast_result_loc(irb, arg_type, no_result); + ir_build_reset_result(ag, scope, source_node, no_result); + ResultLocCast *result_loc_cast = ir_build_cast_result_loc(ag, arg_type, no_result); - IrInstSrc *arg = ir_gen_node_extra(irb, arg_node, scope, LValNone, &result_loc_cast->base); - if (arg == irb->codegen->invalid_inst_src) + IrInstSrc *arg = ir_gen_node_extra(ag, arg_node, scope, LValNone, &result_loc_cast->base); + if (arg == ag->codegen->invalid_inst_src) return arg; - args[i] = ir_build_implicit_cast(irb, scope, arg_node, arg, result_loc_cast); + args[i] = ir_build_implicit_cast(ag, scope, arg_node, arg, result_loc_cast); } IrInstSrc *fn_call; if (options != nullptr) { - fn_call = ir_build_call_args(irb, scope, source_node, options, fn_ref, args, args_len, result_loc); + fn_call = ir_build_call_args(ag, scope, source_node, options, fn_ref, args, args_len, result_loc); } else { - fn_call = ir_build_call_src(irb, scope, source_node, nullptr, fn_ref, args_len, args, nullptr, + fn_call = ir_build_call_src(ag, scope, source_node, nullptr, fn_ref, args_len, args, nullptr, modifier, false, nullptr, result_loc); } - return ir_lval_wrap(irb, scope, fn_call, lval, result_loc); + return ir_lval_wrap(ag, scope, fn_call, lval, result_loc); } -static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, +static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypeFnCallExpr); AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr; Buf *name = node_identifier_buf(fn_ref_expr); - auto entry = irb->codegen->builtin_fn_table.maybe_get(name); + auto entry = ag->codegen->builtin_fn_table.maybe_get(name); if (!entry) { - add_node_error(irb->codegen, node, + add_node_error(ag->codegen, node, buf_sprintf("invalid builtin function: '%s'", buf_ptr(name))); - return irb->codegen->invalid_inst_src; + return ag->codegen->invalid_inst_src; } BuiltinFnEntry *builtin_fn = entry->value; size_t actual_param_count = node->data.fn_call_expr.params.length; if (builtin_fn->param_count != SIZE_MAX && builtin_fn->param_count != actual_param_count) { - add_node_error(irb->codegen, node, + add_node_error(ag->codegen, node, buf_sprintf("expected %" ZIG_PRI_usize " argument(s), found %" ZIG_PRI_usize, builtin_fn->param_count, actual_param_count)); - return irb->codegen->invalid_inst_src; + return ag->codegen->invalid_inst_src; } switch (builtin_fn->id) { @@ -4124,152 +4124,152 @@ static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNod zig_unreachable(); case BuiltinFnIdTypeof: { - Scope *sub_scope = create_typeof_scope(irb->codegen, node, scope); + Scope *sub_scope = create_typeof_scope(ag->codegen, node, scope); size_t arg_count = node->data.fn_call_expr.params.length; IrInstSrc *type_of; if (arg_count == 0) { - add_node_error(irb->codegen, node, + add_node_error(ag->codegen, node, buf_sprintf("expected at least 1 argument, found 0")); - return irb->codegen->invalid_inst_src; + return ag->codegen->invalid_inst_src; } else if (arg_count == 1) { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, sub_scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, sub_scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; - type_of = ir_build_typeof_1(irb, scope, node, arg0_value); + type_of = ir_build_typeof_1(ag, scope, node, arg0_value); } else { IrInstSrc **args = heap::c_allocator.allocate(arg_count); for (size_t i = 0; i < arg_count; i += 1) { AstNode *arg_node = node->data.fn_call_expr.params.at(i); - IrInstSrc *arg = ir_gen_node(irb, arg_node, sub_scope); - if (arg == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; + IrInstSrc *arg = ir_gen_node(ag, arg_node, sub_scope); + if (arg == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; args[i] = arg; } - type_of = ir_build_typeof_n(irb, scope, node, args, arg_count); + type_of = ir_build_typeof_n(ag, scope, node, args, arg_count); } - return ir_lval_wrap(irb, scope, type_of, lval, result_loc); + return ir_lval_wrap(ag, scope, type_of, lval, result_loc); } case BuiltinFnIdSetCold: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; - IrInstSrc *set_cold = ir_build_set_cold(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, set_cold, lval, result_loc); + IrInstSrc *set_cold = ir_build_set_cold(ag, scope, node, arg0_value); + return ir_lval_wrap(ag, scope, set_cold, lval, result_loc); } case BuiltinFnIdSetRuntimeSafety: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; - IrInstSrc *set_safety = ir_build_set_runtime_safety(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, set_safety, lval, result_loc); + IrInstSrc *set_safety = ir_build_set_runtime_safety(ag, scope, node, arg0_value); + return ir_lval_wrap(ag, scope, set_safety, lval, result_loc); } case BuiltinFnIdSetFloatMode: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; - IrInstSrc *set_float_mode = ir_build_set_float_mode(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, set_float_mode, lval, result_loc); + IrInstSrc *set_float_mode = ir_build_set_float_mode(ag, scope, node, arg0_value); + return ir_lval_wrap(ag, scope, set_float_mode, lval, result_loc); } case BuiltinFnIdSizeof: case BuiltinFnIdBitSizeof: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; - IrInstSrc *size_of = ir_build_size_of(irb, scope, node, arg0_value, builtin_fn->id == BuiltinFnIdBitSizeof); - return ir_lval_wrap(irb, scope, size_of, lval, result_loc); + IrInstSrc *size_of = ir_build_size_of(ag, scope, node, arg0_value, builtin_fn->id == BuiltinFnIdBitSizeof); + return ir_lval_wrap(ag, scope, size_of, lval, result_loc); } case BuiltinFnIdImport: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; - IrInstSrc *import = ir_build_import(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, import, lval, result_loc); + IrInstSrc *import = ir_build_import(ag, scope, node, arg0_value); + return ir_lval_wrap(ag, scope, import, lval, result_loc); } case BuiltinFnIdCImport: { - IrInstSrc *c_import = ir_build_c_import(irb, scope, node); - return ir_lval_wrap(irb, scope, c_import, lval, result_loc); + IrInstSrc *c_import = ir_build_c_import(ag, scope, node); + return ir_lval_wrap(ag, scope, c_import, lval, result_loc); } case BuiltinFnIdCInclude: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; - if (!exec_c_import_buf(irb->exec)) { - add_node_error(irb->codegen, node, buf_sprintf("C include valid only inside C import block")); - return irb->codegen->invalid_inst_src; + if (!exec_c_import_buf(ag->exec)) { + add_node_error(ag->codegen, node, buf_sprintf("C include valid only inside C import block")); + return ag->codegen->invalid_inst_src; } - IrInstSrc *c_include = ir_build_c_include(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, c_include, lval, result_loc); + IrInstSrc *c_include = ir_build_c_include(ag, scope, node, arg0_value); + return ir_lval_wrap(ag, scope, c_include, lval, result_loc); } case BuiltinFnIdCDefine: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; - if (!exec_c_import_buf(irb->exec)) { - add_node_error(irb->codegen, node, buf_sprintf("C define valid only inside C import block")); - return irb->codegen->invalid_inst_src; + if (!exec_c_import_buf(ag->exec)) { + add_node_error(ag->codegen, node, buf_sprintf("C define valid only inside C import block")); + return ag->codegen->invalid_inst_src; } - IrInstSrc *c_define = ir_build_c_define(irb, scope, node, arg0_value, arg1_value); - return ir_lval_wrap(irb, scope, c_define, lval, result_loc); + IrInstSrc *c_define = ir_build_c_define(ag, scope, node, arg0_value, arg1_value); + return ir_lval_wrap(ag, scope, c_define, lval, result_loc); } case BuiltinFnIdCUndef: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; - if (!exec_c_import_buf(irb->exec)) { - add_node_error(irb->codegen, node, buf_sprintf("C undef valid only inside C import block")); - return irb->codegen->invalid_inst_src; + if (!exec_c_import_buf(ag->exec)) { + add_node_error(ag->codegen, node, buf_sprintf("C undef valid only inside C import block")); + return ag->codegen->invalid_inst_src; } - IrInstSrc *c_undef = ir_build_c_undef(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, c_undef, lval, result_loc); + IrInstSrc *c_undef = ir_build_c_undef(ag, scope, node, arg0_value); + return ir_lval_wrap(ag, scope, c_undef, lval, result_loc); } case BuiltinFnIdCompileErr: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; - IrInstSrc *compile_err = ir_build_compile_err(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, compile_err, lval, result_loc); + IrInstSrc *compile_err = ir_build_compile_err(ag, scope, node, arg0_value); + return ir_lval_wrap(ag, scope, compile_err, lval, result_loc); } case BuiltinFnIdCompileLog: { @@ -4277,171 +4277,171 @@ static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNod for (size_t i = 0; i < actual_param_count; i += 1) { AstNode *arg_node = node->data.fn_call_expr.params.at(i); - args[i] = ir_gen_node(irb, arg_node, scope); - if (args[i] == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; + args[i] = ir_gen_node(ag, arg_node, scope); + if (args[i] == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; } - IrInstSrc *compile_log = ir_build_compile_log(irb, scope, node, actual_param_count, args); - return ir_lval_wrap(irb, scope, compile_log, lval, result_loc); + IrInstSrc *compile_log = ir_build_compile_log(ag, scope, node, actual_param_count, args); + return ir_lval_wrap(ag, scope, compile_log, lval, result_loc); } case BuiltinFnIdErrName: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; - IrInstSrc *err_name = ir_build_err_name(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, err_name, lval, result_loc); + IrInstSrc *err_name = ir_build_err_name(ag, scope, node, arg0_value); + return ir_lval_wrap(ag, scope, err_name, lval, result_loc); } case BuiltinFnIdEmbedFile: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; - IrInstSrc *embed_file = ir_build_embed_file(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, embed_file, lval, result_loc); + IrInstSrc *embed_file = ir_build_embed_file(ag, scope, node, arg0_value); + return ir_lval_wrap(ag, scope, embed_file, lval, result_loc); } case BuiltinFnIdCmpxchgWeak: case BuiltinFnIdCmpxchgStrong: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; AstNode *arg2_node = node->data.fn_call_expr.params.at(2); - IrInstSrc *arg2_value = ir_gen_node(irb, arg2_node, scope); - if (arg2_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg2_value = ir_gen_node(ag, arg2_node, scope); + if (arg2_value == ag->codegen->invalid_inst_src) return arg2_value; AstNode *arg3_node = node->data.fn_call_expr.params.at(3); - IrInstSrc *arg3_value = ir_gen_node(irb, arg3_node, scope); - if (arg3_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg3_value = ir_gen_node(ag, arg3_node, scope); + if (arg3_value == ag->codegen->invalid_inst_src) return arg3_value; AstNode *arg4_node = node->data.fn_call_expr.params.at(4); - IrInstSrc *arg4_value = ir_gen_node(irb, arg4_node, scope); - if (arg4_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg4_value = ir_gen_node(ag, arg4_node, scope); + if (arg4_value == ag->codegen->invalid_inst_src) return arg4_value; AstNode *arg5_node = node->data.fn_call_expr.params.at(5); - IrInstSrc *arg5_value = ir_gen_node(irb, arg5_node, scope); - if (arg5_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg5_value = ir_gen_node(ag, arg5_node, scope); + if (arg5_value == ag->codegen->invalid_inst_src) return arg5_value; - IrInstSrc *cmpxchg = ir_build_cmpxchg_src(irb, scope, node, arg0_value, arg1_value, + IrInstSrc *cmpxchg = ir_build_cmpxchg_src(ag, scope, node, arg0_value, arg1_value, arg2_value, arg3_value, arg4_value, arg5_value, (builtin_fn->id == BuiltinFnIdCmpxchgWeak), result_loc); - return ir_lval_wrap(irb, scope, cmpxchg, lval, result_loc); + return ir_lval_wrap(ag, scope, cmpxchg, lval, result_loc); } case BuiltinFnIdFence: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; - IrInstSrc *fence = ir_build_fence(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, fence, lval, result_loc); + IrInstSrc *fence = ir_build_fence(ag, scope, node, arg0_value); + return ir_lval_wrap(ag, scope, fence, lval, result_loc); } case BuiltinFnIdReduce: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; - IrInstSrc *reduce = ir_build_reduce(irb, scope, node, arg0_value, arg1_value); - return ir_lval_wrap(irb, scope, reduce, lval, result_loc); + IrInstSrc *reduce = ir_build_reduce(ag, scope, node, arg0_value, arg1_value); + return ir_lval_wrap(ag, scope, reduce, lval, result_loc); } case BuiltinFnIdDivExact: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; - IrInstSrc *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpDivExact, arg0_value, arg1_value, true); - return ir_lval_wrap(irb, scope, bin_op, lval, result_loc); + IrInstSrc *bin_op = ir_build_bin_op(ag, scope, node, IrBinOpDivExact, arg0_value, arg1_value, true); + return ir_lval_wrap(ag, scope, bin_op, lval, result_loc); } case BuiltinFnIdDivTrunc: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; - IrInstSrc *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpDivTrunc, arg0_value, arg1_value, true); - return ir_lval_wrap(irb, scope, bin_op, lval, result_loc); + IrInstSrc *bin_op = ir_build_bin_op(ag, scope, node, IrBinOpDivTrunc, arg0_value, arg1_value, true); + return ir_lval_wrap(ag, scope, bin_op, lval, result_loc); } case BuiltinFnIdDivFloor: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; - IrInstSrc *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpDivFloor, arg0_value, arg1_value, true); - return ir_lval_wrap(irb, scope, bin_op, lval, result_loc); + IrInstSrc *bin_op = ir_build_bin_op(ag, scope, node, IrBinOpDivFloor, arg0_value, arg1_value, true); + return ir_lval_wrap(ag, scope, bin_op, lval, result_loc); } case BuiltinFnIdRem: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; - IrInstSrc *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpRemRem, arg0_value, arg1_value, true); - return ir_lval_wrap(irb, scope, bin_op, lval, result_loc); + IrInstSrc *bin_op = ir_build_bin_op(ag, scope, node, IrBinOpRemRem, arg0_value, arg1_value, true); + return ir_lval_wrap(ag, scope, bin_op, lval, result_loc); } case BuiltinFnIdMod: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; - IrInstSrc *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpRemMod, arg0_value, arg1_value, true); - return ir_lval_wrap(irb, scope, bin_op, lval, result_loc); + IrInstSrc *bin_op = ir_build_bin_op(ag, scope, node, IrBinOpRemMod, arg0_value, arg1_value, true); + return ir_lval_wrap(ag, scope, bin_op, lval, result_loc); } case BuiltinFnIdSqrt: case BuiltinFnIdSin: @@ -4459,537 +4459,537 @@ static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNod case BuiltinFnIdRound: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; - IrInstSrc *inst = ir_build_float_op_src(irb, scope, node, arg0_value, builtin_fn->id); - return ir_lval_wrap(irb, scope, inst, lval, result_loc); + IrInstSrc *inst = ir_build_float_op_src(ag, scope, node, arg0_value, builtin_fn->id); + return ir_lval_wrap(ag, scope, inst, lval, result_loc); } case BuiltinFnIdTruncate: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; - IrInstSrc *truncate = ir_build_truncate(irb, scope, node, arg0_value, arg1_value); - return ir_lval_wrap(irb, scope, truncate, lval, result_loc); + IrInstSrc *truncate = ir_build_truncate(ag, scope, node, arg0_value, arg1_value); + return ir_lval_wrap(ag, scope, truncate, lval, result_loc); } case BuiltinFnIdIntCast: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; - IrInstSrc *result = ir_build_int_cast(irb, scope, node, arg0_value, arg1_value); - return ir_lval_wrap(irb, scope, result, lval, result_loc); + IrInstSrc *result = ir_build_int_cast(ag, scope, node, arg0_value, arg1_value); + return ir_lval_wrap(ag, scope, result, lval, result_loc); } case BuiltinFnIdFloatCast: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; - IrInstSrc *result = ir_build_float_cast(irb, scope, node, arg0_value, arg1_value); - return ir_lval_wrap(irb, scope, result, lval, result_loc); + IrInstSrc *result = ir_build_float_cast(ag, scope, node, arg0_value, arg1_value); + return ir_lval_wrap(ag, scope, result, lval, result_loc); } case BuiltinFnIdErrSetCast: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; - IrInstSrc *result = ir_build_err_set_cast(irb, scope, node, arg0_value, arg1_value); - return ir_lval_wrap(irb, scope, result, lval, result_loc); + IrInstSrc *result = ir_build_err_set_cast(ag, scope, node, arg0_value, arg1_value); + return ir_lval_wrap(ag, scope, result, lval, result_loc); } case BuiltinFnIdIntToFloat: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; - IrInstSrc *result = ir_build_int_to_float(irb, scope, node, arg0_value, arg1_value); - return ir_lval_wrap(irb, scope, result, lval, result_loc); + IrInstSrc *result = ir_build_int_to_float(ag, scope, node, arg0_value, arg1_value); + return ir_lval_wrap(ag, scope, result, lval, result_loc); } case BuiltinFnIdFloatToInt: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; - IrInstSrc *result = ir_build_float_to_int(irb, scope, node, arg0_value, arg1_value); - return ir_lval_wrap(irb, scope, result, lval, result_loc); + IrInstSrc *result = ir_build_float_to_int(ag, scope, node, arg0_value, arg1_value); + return ir_lval_wrap(ag, scope, result, lval, result_loc); } case BuiltinFnIdErrToInt: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; - IrInstSrc *result = ir_build_err_to_int_src(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, result, lval, result_loc); + IrInstSrc *result = ir_build_err_to_int_src(ag, scope, node, arg0_value); + return ir_lval_wrap(ag, scope, result, lval, result_loc); } case BuiltinFnIdIntToErr: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; - IrInstSrc *result = ir_build_int_to_err_src(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, result, lval, result_loc); + IrInstSrc *result = ir_build_int_to_err_src(ag, scope, node, arg0_value); + return ir_lval_wrap(ag, scope, result, lval, result_loc); } case BuiltinFnIdBoolToInt: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; - IrInstSrc *result = ir_build_bool_to_int(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, result, lval, result_loc); + IrInstSrc *result = ir_build_bool_to_int(ag, scope, node, arg0_value); + return ir_lval_wrap(ag, scope, result, lval, result_loc); } case BuiltinFnIdVectorType: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; - IrInstSrc *vector_type = ir_build_vector_type(irb, scope, node, arg0_value, arg1_value); - return ir_lval_wrap(irb, scope, vector_type, lval, result_loc); + IrInstSrc *vector_type = ir_build_vector_type(ag, scope, node, arg0_value, arg1_value); + return ir_lval_wrap(ag, scope, vector_type, lval, result_loc); } case BuiltinFnIdShuffle: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; AstNode *arg2_node = node->data.fn_call_expr.params.at(2); - IrInstSrc *arg2_value = ir_gen_node(irb, arg2_node, scope); - if (arg2_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg2_value = ir_gen_node(ag, arg2_node, scope); + if (arg2_value == ag->codegen->invalid_inst_src) return arg2_value; AstNode *arg3_node = node->data.fn_call_expr.params.at(3); - IrInstSrc *arg3_value = ir_gen_node(irb, arg3_node, scope); - if (arg3_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg3_value = ir_gen_node(ag, arg3_node, scope); + if (arg3_value == ag->codegen->invalid_inst_src) return arg3_value; - IrInstSrc *shuffle_vector = ir_build_shuffle_vector(irb, scope, node, + IrInstSrc *shuffle_vector = ir_build_shuffle_vector(ag, scope, node, arg0_value, arg1_value, arg2_value, arg3_value); - return ir_lval_wrap(irb, scope, shuffle_vector, lval, result_loc); + return ir_lval_wrap(ag, scope, shuffle_vector, lval, result_loc); } case BuiltinFnIdSplat: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; - IrInstSrc *splat = ir_build_splat_src(irb, scope, node, + IrInstSrc *splat = ir_build_splat_src(ag, scope, node, arg0_value, arg1_value); - return ir_lval_wrap(irb, scope, splat, lval, result_loc); + return ir_lval_wrap(ag, scope, splat, lval, result_loc); } case BuiltinFnIdMemcpy: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; AstNode *arg2_node = node->data.fn_call_expr.params.at(2); - IrInstSrc *arg2_value = ir_gen_node(irb, arg2_node, scope); - if (arg2_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg2_value = ir_gen_node(ag, arg2_node, scope); + if (arg2_value == ag->codegen->invalid_inst_src) return arg2_value; - IrInstSrc *ir_memcpy = ir_build_memcpy_src(irb, scope, node, arg0_value, arg1_value, arg2_value); - return ir_lval_wrap(irb, scope, ir_memcpy, lval, result_loc); + IrInstSrc *ir_memcpy = ir_build_memcpy_src(ag, scope, node, arg0_value, arg1_value, arg2_value); + return ir_lval_wrap(ag, scope, ir_memcpy, lval, result_loc); } case BuiltinFnIdMemset: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; AstNode *arg2_node = node->data.fn_call_expr.params.at(2); - IrInstSrc *arg2_value = ir_gen_node(irb, arg2_node, scope); - if (arg2_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg2_value = ir_gen_node(ag, arg2_node, scope); + if (arg2_value == ag->codegen->invalid_inst_src) return arg2_value; - IrInstSrc *ir_memset = ir_build_memset_src(irb, scope, node, arg0_value, arg1_value, arg2_value); - return ir_lval_wrap(irb, scope, ir_memset, lval, result_loc); + IrInstSrc *ir_memset = ir_build_memset_src(ag, scope, node, arg0_value, arg1_value, arg2_value); + return ir_lval_wrap(ag, scope, ir_memset, lval, result_loc); } case BuiltinFnIdWasmMemorySize: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; - IrInstSrc *ir_wasm_memory_size = ir_build_wasm_memory_size_src(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, ir_wasm_memory_size, lval, result_loc); + IrInstSrc *ir_wasm_memory_size = ir_build_wasm_memory_size_src(ag, scope, node, arg0_value); + return ir_lval_wrap(ag, scope, ir_wasm_memory_size, lval, result_loc); } case BuiltinFnIdWasmMemoryGrow: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; - IrInstSrc *ir_wasm_memory_grow = ir_build_wasm_memory_grow_src(irb, scope, node, arg0_value, arg1_value); - return ir_lval_wrap(irb, scope, ir_wasm_memory_grow, lval, result_loc); + IrInstSrc *ir_wasm_memory_grow = ir_build_wasm_memory_grow_src(ag, scope, node, arg0_value, arg1_value); + return ir_lval_wrap(ag, scope, ir_wasm_memory_grow, lval, result_loc); } case BuiltinFnIdField: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node_extra(irb, arg0_node, scope, LValPtr, nullptr); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node_extra(ag, arg0_node, scope, LValPtr, nullptr); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; - IrInstSrc *ptr_instruction = ir_build_field_ptr_instruction(irb, scope, node, + IrInstSrc *ptr_instruction = ir_build_field_ptr_instruction(ag, scope, node, arg0_value, arg1_value, false); if (lval == LValPtr || lval == LValAssign) return ptr_instruction; - IrInstSrc *load_ptr = ir_build_load_ptr(irb, scope, node, ptr_instruction); - return ir_expr_wrap(irb, scope, load_ptr, result_loc); + IrInstSrc *load_ptr = ir_build_load_ptr(ag, scope, node, ptr_instruction); + return ir_expr_wrap(ag, scope, load_ptr, result_loc); } case BuiltinFnIdHasField: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; - IrInstSrc *type_info = ir_build_has_field(irb, scope, node, arg0_value, arg1_value); - return ir_lval_wrap(irb, scope, type_info, lval, result_loc); + IrInstSrc *type_info = ir_build_has_field(ag, scope, node, arg0_value, arg1_value); + return ir_lval_wrap(ag, scope, type_info, lval, result_loc); } case BuiltinFnIdTypeInfo: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; - IrInstSrc *type_info = ir_build_type_info(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, type_info, lval, result_loc); + IrInstSrc *type_info = ir_build_type_info(ag, scope, node, arg0_value); + return ir_lval_wrap(ag, scope, type_info, lval, result_loc); } case BuiltinFnIdType: { AstNode *arg_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg = ir_gen_node(irb, arg_node, scope); - if (arg == irb->codegen->invalid_inst_src) + IrInstSrc *arg = ir_gen_node(ag, arg_node, scope); + if (arg == ag->codegen->invalid_inst_src) return arg; - IrInstSrc *type = ir_build_type(irb, scope, node, arg); - return ir_lval_wrap(irb, scope, type, lval, result_loc); + IrInstSrc *type = ir_build_type(ag, scope, node, arg); + return ir_lval_wrap(ag, scope, type, lval, result_loc); } case BuiltinFnIdBreakpoint: - return ir_lval_wrap(irb, scope, ir_build_breakpoint(irb, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_build_breakpoint(ag, scope, node), lval, result_loc); case BuiltinFnIdReturnAddress: - return ir_lval_wrap(irb, scope, ir_build_return_address_src(irb, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_build_return_address_src(ag, scope, node), lval, result_loc); case BuiltinFnIdFrameAddress: - return ir_lval_wrap(irb, scope, ir_build_frame_address_src(irb, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_build_frame_address_src(ag, scope, node), lval, result_loc); case BuiltinFnIdFrameHandle: - if (!irb->exec->fn_entry) { - add_node_error(irb->codegen, node, buf_sprintf("@frame() called outside of function definition")); - return irb->codegen->invalid_inst_src; + if (!ag->exec->fn_entry) { + add_node_error(ag->codegen, node, buf_sprintf("@frame() called outside of function definition")); + return ag->codegen->invalid_inst_src; } - return ir_lval_wrap(irb, scope, ir_build_handle_src(irb, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_build_handle_src(ag, scope, node), lval, result_loc); case BuiltinFnIdFrameType: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; - IrInstSrc *frame_type = ir_build_frame_type(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, frame_type, lval, result_loc); + IrInstSrc *frame_type = ir_build_frame_type(ag, scope, node, arg0_value); + return ir_lval_wrap(ag, scope, frame_type, lval, result_loc); } case BuiltinFnIdFrameSize: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; - IrInstSrc *frame_size = ir_build_frame_size_src(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, frame_size, lval, result_loc); + IrInstSrc *frame_size = ir_build_frame_size_src(ag, scope, node, arg0_value); + return ir_lval_wrap(ag, scope, frame_size, lval, result_loc); } case BuiltinFnIdAlignOf: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; - IrInstSrc *align_of = ir_build_align_of(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, align_of, lval, result_loc); + IrInstSrc *align_of = ir_build_align_of(ag, scope, node, arg0_value); + return ir_lval_wrap(ag, scope, align_of, lval, result_loc); } case BuiltinFnIdAddWithOverflow: - return ir_lval_wrap(irb, scope, ir_gen_overflow_op(irb, scope, node, IrOverflowOpAdd), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_overflow_op(ag, scope, node, IrOverflowOpAdd), lval, result_loc); case BuiltinFnIdSubWithOverflow: - return ir_lval_wrap(irb, scope, ir_gen_overflow_op(irb, scope, node, IrOverflowOpSub), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_overflow_op(ag, scope, node, IrOverflowOpSub), lval, result_loc); case BuiltinFnIdMulWithOverflow: - return ir_lval_wrap(irb, scope, ir_gen_overflow_op(irb, scope, node, IrOverflowOpMul), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_overflow_op(ag, scope, node, IrOverflowOpMul), lval, result_loc); case BuiltinFnIdShlWithOverflow: - return ir_lval_wrap(irb, scope, ir_gen_overflow_op(irb, scope, node, IrOverflowOpShl), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_overflow_op(ag, scope, node, IrOverflowOpShl), lval, result_loc); case BuiltinFnIdMulAdd: - return ir_lval_wrap(irb, scope, ir_gen_mul_add(irb, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_mul_add(ag, scope, node), lval, result_loc); case BuiltinFnIdTypeName: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; - IrInstSrc *type_name = ir_build_type_name(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, type_name, lval, result_loc); + IrInstSrc *type_name = ir_build_type_name(ag, scope, node, arg0_value); + return ir_lval_wrap(ag, scope, type_name, lval, result_loc); } case BuiltinFnIdPanic: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; - IrInstSrc *panic = ir_build_panic_src(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, panic, lval, result_loc); + IrInstSrc *panic = ir_build_panic_src(ag, scope, node, arg0_value); + return ir_lval_wrap(ag, scope, panic, lval, result_loc); } case BuiltinFnIdPtrCast: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; - IrInstSrc *ptr_cast = ir_build_ptr_cast_src(irb, scope, node, arg0_value, arg1_value, true); - return ir_lval_wrap(irb, scope, ptr_cast, lval, result_loc); + IrInstSrc *ptr_cast = ir_build_ptr_cast_src(ag, scope, node, arg0_value, arg1_value, true); + return ir_lval_wrap(ag, scope, ptr_cast, lval, result_loc); } case BuiltinFnIdBitCast: { AstNode *dest_type_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *dest_type = ir_gen_node(irb, dest_type_node, scope); - if (dest_type == irb->codegen->invalid_inst_src) + IrInstSrc *dest_type = ir_gen_node(ag, dest_type_node, scope); + if (dest_type == ag->codegen->invalid_inst_src) return dest_type; ResultLocBitCast *result_loc_bit_cast = heap::c_allocator.create(); result_loc_bit_cast->base.id = ResultLocIdBitCast; result_loc_bit_cast->base.source_instruction = dest_type; result_loc_bit_cast->base.allow_write_through_const = result_loc->allow_write_through_const; - ir_ref_instruction(dest_type, irb->current_basic_block); + ir_ref_instruction(dest_type, ag->current_basic_block); result_loc_bit_cast->parent = result_loc; - ir_build_reset_result(irb, scope, node, &result_loc_bit_cast->base); + ir_build_reset_result(ag, scope, node, &result_loc_bit_cast->base); AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node_extra(irb, arg1_node, scope, LValNone, + IrInstSrc *arg1_value = ir_gen_node_extra(ag, arg1_node, scope, LValNone, &result_loc_bit_cast->base); - if (arg1_value == irb->codegen->invalid_inst_src) + if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; - IrInstSrc *bitcast = ir_build_bit_cast_src(irb, scope, arg1_node, arg1_value, result_loc_bit_cast); - return ir_lval_wrap(irb, scope, bitcast, lval, result_loc); + IrInstSrc *bitcast = ir_build_bit_cast_src(ag, scope, arg1_node, arg1_value, result_loc_bit_cast); + return ir_lval_wrap(ag, scope, bitcast, lval, result_loc); } case BuiltinFnIdAs: { AstNode *dest_type_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *dest_type = ir_gen_node(irb, dest_type_node, scope); - if (dest_type == irb->codegen->invalid_inst_src) + IrInstSrc *dest_type = ir_gen_node(ag, dest_type_node, scope); + if (dest_type == ag->codegen->invalid_inst_src) return dest_type; - ResultLocCast *result_loc_cast = ir_build_cast_result_loc(irb, dest_type, result_loc); + ResultLocCast *result_loc_cast = ir_build_cast_result_loc(ag, dest_type, result_loc); AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node_extra(irb, arg1_node, scope, LValNone, + IrInstSrc *arg1_value = ir_gen_node_extra(ag, arg1_node, scope, LValNone, &result_loc_cast->base); - if (arg1_value == irb->codegen->invalid_inst_src) + if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; - IrInstSrc *result = ir_build_implicit_cast(irb, scope, node, arg1_value, result_loc_cast); - return ir_lval_wrap(irb, scope, result, lval, result_loc); + IrInstSrc *result = ir_build_implicit_cast(ag, scope, node, arg1_value, result_loc_cast); + return ir_lval_wrap(ag, scope, result, lval, result_loc); } case BuiltinFnIdIntToPtr: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; - IrInstSrc *int_to_ptr = ir_build_int_to_ptr_src(irb, scope, node, arg0_value, arg1_value); - return ir_lval_wrap(irb, scope, int_to_ptr, lval, result_loc); + IrInstSrc *int_to_ptr = ir_build_int_to_ptr_src(ag, scope, node, arg0_value, arg1_value); + return ir_lval_wrap(ag, scope, int_to_ptr, lval, result_loc); } case BuiltinFnIdPtrToInt: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; - IrInstSrc *ptr_to_int = ir_build_ptr_to_int_src(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, ptr_to_int, lval, result_loc); + IrInstSrc *ptr_to_int = ir_build_ptr_to_int_src(ag, scope, node, arg0_value); + return ir_lval_wrap(ag, scope, ptr_to_int, lval, result_loc); } case BuiltinFnIdTagName: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; - IrInstSrc *tag_name = ir_build_tag_name_src(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, tag_name, lval, result_loc); + IrInstSrc *tag_name = ir_build_tag_name_src(ag, scope, node, arg0_value); + return ir_lval_wrap(ag, scope, tag_name, lval, result_loc); } case BuiltinFnIdFieldParentPtr: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; AstNode *arg2_node = node->data.fn_call_expr.params.at(2); - IrInstSrc *arg2_value = ir_gen_node(irb, arg2_node, scope); - if (arg2_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg2_value = ir_gen_node(ag, arg2_node, scope); + if (arg2_value == ag->codegen->invalid_inst_src) return arg2_value; - IrInstSrc *field_parent_ptr = ir_build_field_parent_ptr_src(irb, scope, node, + IrInstSrc *field_parent_ptr = ir_build_field_parent_ptr_src(ag, scope, node, arg0_value, arg1_value, arg2_value); - return ir_lval_wrap(irb, scope, field_parent_ptr, lval, result_loc); + return ir_lval_wrap(ag, scope, field_parent_ptr, lval, result_loc); } case BuiltinFnIdByteOffsetOf: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; - IrInstSrc *offset_of = ir_build_byte_offset_of(irb, scope, node, arg0_value, arg1_value); - return ir_lval_wrap(irb, scope, offset_of, lval, result_loc); + IrInstSrc *offset_of = ir_build_byte_offset_of(ag, scope, node, arg0_value, arg1_value); + return ir_lval_wrap(ag, scope, offset_of, lval, result_loc); } case BuiltinFnIdBitOffsetOf: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; - IrInstSrc *offset_of = ir_build_bit_offset_of(irb, scope, node, arg0_value, arg1_value); - return ir_lval_wrap(irb, scope, offset_of, lval, result_loc); + IrInstSrc *offset_of = ir_build_bit_offset_of(ag, scope, node, arg0_value, arg1_value); + return ir_lval_wrap(ag, scope, offset_of, lval, result_loc); } case BuiltinFnIdCall: { // Cast the options parameter to the options type - ZigType *options_type = get_builtin_type(irb->codegen, "CallOptions"); - IrInstSrc *options_type_inst = ir_build_const_type(irb, scope, node, options_type); - ResultLocCast *result_loc_cast = ir_build_cast_result_loc(irb, options_type_inst, no_result_loc()); + ZigType *options_type = get_builtin_type(ag->codegen, "CallOptions"); + IrInstSrc *options_type_inst = ir_build_const_type(ag, scope, node, options_type); + ResultLocCast *result_loc_cast = ir_build_cast_result_loc(ag, options_type_inst, no_result_loc()); AstNode *options_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *options_inner = ir_gen_node_extra(irb, options_node, scope, + IrInstSrc *options_inner = ir_gen_node_extra(ag, options_node, scope, LValNone, &result_loc_cast->base); - if (options_inner == irb->codegen->invalid_inst_src) + if (options_inner == ag->codegen->invalid_inst_src) return options_inner; - IrInstSrc *options = ir_build_implicit_cast(irb, scope, options_node, options_inner, result_loc_cast); + IrInstSrc *options = ir_build_implicit_cast(ag, scope, options_node, options_inner, result_loc_cast); AstNode *fn_ref_node = node->data.fn_call_expr.params.at(1); AstNode *args_node = node->data.fn_call_expr.params.at(2); @@ -4997,256 +4997,256 @@ static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNod if (args_node->data.container_init_expr.kind == ContainerInitKindArray || args_node->data.container_init_expr.entries.length == 0) { - return ir_gen_fn_call_with_args(irb, scope, node, + return ir_gen_fn_call_with_args(ag, scope, node, fn_ref_node, CallModifierNone, options, args_node->data.container_init_expr.entries.items, args_node->data.container_init_expr.entries.length, lval, result_loc); } else { - exec_add_error_node(irb->codegen, irb->exec, args_node, + exec_add_error_node(ag->codegen, ag->exec, args_node, buf_sprintf("TODO: @call with anon struct literal")); - return irb->codegen->invalid_inst_src; + return ag->codegen->invalid_inst_src; } } else { - IrInstSrc *fn_ref = ir_gen_node(irb, fn_ref_node, scope); - if (fn_ref == irb->codegen->invalid_inst_src) + IrInstSrc *fn_ref = ir_gen_node(ag, fn_ref_node, scope); + if (fn_ref == ag->codegen->invalid_inst_src) return fn_ref; - IrInstSrc *args = ir_gen_node(irb, args_node, scope); - if (args == irb->codegen->invalid_inst_src) + IrInstSrc *args = ir_gen_node(ag, args_node, scope); + if (args == ag->codegen->invalid_inst_src) return args; - IrInstSrc *call = ir_build_call_extra(irb, scope, node, options, fn_ref, args, result_loc); - return ir_lval_wrap(irb, scope, call, lval, result_loc); + IrInstSrc *call = ir_build_call_extra(ag, scope, node, options, fn_ref, args, result_loc); + return ir_lval_wrap(ag, scope, call, lval, result_loc); } } case BuiltinFnIdAsyncCall: - return ir_gen_async_call(irb, scope, nullptr, node, lval, result_loc); + return ir_gen_async_call(ag, scope, nullptr, node, lval, result_loc); case BuiltinFnIdShlExact: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; - IrInstSrc *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpBitShiftLeftExact, arg0_value, arg1_value, true); - return ir_lval_wrap(irb, scope, bin_op, lval, result_loc); + IrInstSrc *bin_op = ir_build_bin_op(ag, scope, node, IrBinOpBitShiftLeftExact, arg0_value, arg1_value, true); + return ir_lval_wrap(ag, scope, bin_op, lval, result_loc); } case BuiltinFnIdShrExact: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; - IrInstSrc *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpBitShiftRightExact, arg0_value, arg1_value, true); - return ir_lval_wrap(irb, scope, bin_op, lval, result_loc); + IrInstSrc *bin_op = ir_build_bin_op(ag, scope, node, IrBinOpBitShiftRightExact, arg0_value, arg1_value, true); + return ir_lval_wrap(ag, scope, bin_op, lval, result_loc); } case BuiltinFnIdSetEvalBranchQuota: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; - IrInstSrc *set_eval_branch_quota = ir_build_set_eval_branch_quota(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, set_eval_branch_quota, lval, result_loc); + IrInstSrc *set_eval_branch_quota = ir_build_set_eval_branch_quota(ag, scope, node, arg0_value); + return ir_lval_wrap(ag, scope, set_eval_branch_quota, lval, result_loc); } case BuiltinFnIdAlignCast: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; - IrInstSrc *align_cast = ir_build_align_cast_src(irb, scope, node, arg0_value, arg1_value); - return ir_lval_wrap(irb, scope, align_cast, lval, result_loc); + IrInstSrc *align_cast = ir_build_align_cast_src(ag, scope, node, arg0_value, arg1_value); + return ir_lval_wrap(ag, scope, align_cast, lval, result_loc); } case BuiltinFnIdThis: { - IrInstSrc *this_inst = ir_gen_this(irb, scope, node); - return ir_lval_wrap(irb, scope, this_inst, lval, result_loc); + IrInstSrc *this_inst = ir_gen_this(ag, scope, node); + return ir_lval_wrap(ag, scope, this_inst, lval, result_loc); } case BuiltinFnIdSetAlignStack: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; - IrInstSrc *set_align_stack = ir_build_set_align_stack(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, set_align_stack, lval, result_loc); + IrInstSrc *set_align_stack = ir_build_set_align_stack(ag, scope, node, arg0_value); + return ir_lval_wrap(ag, scope, set_align_stack, lval, result_loc); } case BuiltinFnIdExport: { // Cast the options parameter to the options type - ZigType *options_type = get_builtin_type(irb->codegen, "ExportOptions"); - IrInstSrc *options_type_inst = ir_build_const_type(irb, scope, node, options_type); - ResultLocCast *result_loc_cast = ir_build_cast_result_loc(irb, options_type_inst, no_result_loc()); + ZigType *options_type = get_builtin_type(ag->codegen, "ExportOptions"); + IrInstSrc *options_type_inst = ir_build_const_type(ag, scope, node, options_type); + ResultLocCast *result_loc_cast = ir_build_cast_result_loc(ag, options_type_inst, no_result_loc()); AstNode *target_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *target_value = ir_gen_node(irb, target_node, scope); - if (target_value == irb->codegen->invalid_inst_src) + IrInstSrc *target_value = ir_gen_node(ag, target_node, scope); + if (target_value == ag->codegen->invalid_inst_src) return target_value; AstNode *options_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *options_value = ir_gen_node_extra(irb, options_node, + IrInstSrc *options_value = ir_gen_node_extra(ag, options_node, scope, LValNone, &result_loc_cast->base); - if (options_value == irb->codegen->invalid_inst_src) + if (options_value == ag->codegen->invalid_inst_src) return options_value; IrInstSrc *casted_options_value = ir_build_implicit_cast( - irb, scope, options_node, options_value, result_loc_cast); + ag, scope, options_node, options_value, result_loc_cast); - IrInstSrc *ir_export = ir_build_export(irb, scope, node, target_value, casted_options_value); - return ir_lval_wrap(irb, scope, ir_export, lval, result_loc); + IrInstSrc *ir_export = ir_build_export(ag, scope, node, target_value, casted_options_value); + return ir_lval_wrap(ag, scope, ir_export, lval, result_loc); } case BuiltinFnIdExtern: { // Cast the options parameter to the options type - ZigType *options_type = get_builtin_type(irb->codegen, "ExternOptions"); - IrInstSrc *options_type_inst = ir_build_const_type(irb, scope, node, options_type); - ResultLocCast *result_loc_cast = ir_build_cast_result_loc(irb, options_type_inst, no_result_loc()); + ZigType *options_type = get_builtin_type(ag->codegen, "ExternOptions"); + IrInstSrc *options_type_inst = ir_build_const_type(ag, scope, node, options_type); + ResultLocCast *result_loc_cast = ir_build_cast_result_loc(ag, options_type_inst, no_result_loc()); AstNode *type_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *type_value = ir_gen_node(irb, type_node, scope); - if (type_value == irb->codegen->invalid_inst_src) + IrInstSrc *type_value = ir_gen_node(ag, type_node, scope); + if (type_value == ag->codegen->invalid_inst_src) return type_value; AstNode *options_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *options_value = ir_gen_node_extra(irb, options_node, + IrInstSrc *options_value = ir_gen_node_extra(ag, options_node, scope, LValNone, &result_loc_cast->base); - if (options_value == irb->codegen->invalid_inst_src) + if (options_value == ag->codegen->invalid_inst_src) return options_value; IrInstSrc *casted_options_value = ir_build_implicit_cast( - irb, scope, options_node, options_value, result_loc_cast); + ag, scope, options_node, options_value, result_loc_cast); - IrInstSrc *ir_extern = ir_build_extern(irb, scope, node, type_value, casted_options_value); - return ir_lval_wrap(irb, scope, ir_extern, lval, result_loc); + IrInstSrc *ir_extern = ir_build_extern(ag, scope, node, type_value, casted_options_value); + return ir_lval_wrap(ag, scope, ir_extern, lval, result_loc); } case BuiltinFnIdErrorReturnTrace: { - IrInstSrc *error_return_trace = ir_build_error_return_trace_src(irb, scope, node, + IrInstSrc *error_return_trace = ir_build_error_return_trace_src(ag, scope, node, IrInstErrorReturnTraceNull); - return ir_lval_wrap(irb, scope, error_return_trace, lval, result_loc); + return ir_lval_wrap(ag, scope, error_return_trace, lval, result_loc); } case BuiltinFnIdAtomicRmw: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; AstNode *arg2_node = node->data.fn_call_expr.params.at(2); - IrInstSrc *arg2_value = ir_gen_node(irb, arg2_node, scope); - if (arg2_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg2_value = ir_gen_node(ag, arg2_node, scope); + if (arg2_value == ag->codegen->invalid_inst_src) return arg2_value; AstNode *arg3_node = node->data.fn_call_expr.params.at(3); - IrInstSrc *arg3_value = ir_gen_node(irb, arg3_node, scope); - if (arg3_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg3_value = ir_gen_node(ag, arg3_node, scope); + if (arg3_value == ag->codegen->invalid_inst_src) return arg3_value; AstNode *arg4_node = node->data.fn_call_expr.params.at(4); - IrInstSrc *arg4_value = ir_gen_node(irb, arg4_node, scope); - if (arg4_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg4_value = ir_gen_node(ag, arg4_node, scope); + if (arg4_value == ag->codegen->invalid_inst_src) return arg4_value; - IrInstSrc *inst = ir_build_atomic_rmw_src(irb, scope, node, + IrInstSrc *inst = ir_build_atomic_rmw_src(ag, scope, node, arg0_value, arg1_value, arg2_value, arg3_value, arg4_value); - return ir_lval_wrap(irb, scope, inst, lval, result_loc); + return ir_lval_wrap(ag, scope, inst, lval, result_loc); } case BuiltinFnIdAtomicLoad: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; AstNode *arg2_node = node->data.fn_call_expr.params.at(2); - IrInstSrc *arg2_value = ir_gen_node(irb, arg2_node, scope); - if (arg2_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg2_value = ir_gen_node(ag, arg2_node, scope); + if (arg2_value == ag->codegen->invalid_inst_src) return arg2_value; - IrInstSrc *inst = ir_build_atomic_load_src(irb, scope, node, arg0_value, arg1_value, arg2_value); - return ir_lval_wrap(irb, scope, inst, lval, result_loc); + IrInstSrc *inst = ir_build_atomic_load_src(ag, scope, node, arg0_value, arg1_value, arg2_value); + return ir_lval_wrap(ag, scope, inst, lval, result_loc); } case BuiltinFnIdAtomicStore: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; AstNode *arg2_node = node->data.fn_call_expr.params.at(2); - IrInstSrc *arg2_value = ir_gen_node(irb, arg2_node, scope); - if (arg2_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg2_value = ir_gen_node(ag, arg2_node, scope); + if (arg2_value == ag->codegen->invalid_inst_src) return arg2_value; AstNode *arg3_node = node->data.fn_call_expr.params.at(3); - IrInstSrc *arg3_value = ir_gen_node(irb, arg3_node, scope); - if (arg3_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg3_value = ir_gen_node(ag, arg3_node, scope); + if (arg3_value == ag->codegen->invalid_inst_src) return arg3_value; - IrInstSrc *inst = ir_build_atomic_store_src(irb, scope, node, arg0_value, arg1_value, + IrInstSrc *inst = ir_build_atomic_store_src(ag, scope, node, arg0_value, arg1_value, arg2_value, arg3_value); - return ir_lval_wrap(irb, scope, inst, lval, result_loc); + return ir_lval_wrap(ag, scope, inst, lval, result_loc); } case BuiltinFnIdIntToEnum: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; - IrInstSrc *result = ir_build_int_to_enum_src(irb, scope, node, arg0_value, arg1_value); - return ir_lval_wrap(irb, scope, result, lval, result_loc); + IrInstSrc *result = ir_build_int_to_enum_src(ag, scope, node, arg0_value, arg1_value); + return ir_lval_wrap(ag, scope, result, lval, result_loc); } case BuiltinFnIdEnumToInt: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; - IrInstSrc *result = ir_build_enum_to_int(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, result, lval, result_loc); + IrInstSrc *result = ir_build_enum_to_int(ag, scope, node, arg0_value); + return ir_lval_wrap(ag, scope, result, lval, result_loc); } case BuiltinFnIdCtz: case BuiltinFnIdPopCount: @@ -5255,73 +5255,73 @@ static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNod case BuiltinFnIdBitReverse: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; IrInstSrc *result; switch (builtin_fn->id) { case BuiltinFnIdCtz: - result = ir_build_ctz(irb, scope, node, arg0_value, arg1_value); + result = ir_build_ctz(ag, scope, node, arg0_value, arg1_value); break; case BuiltinFnIdPopCount: - result = ir_build_pop_count(irb, scope, node, arg0_value, arg1_value); + result = ir_build_pop_count(ag, scope, node, arg0_value, arg1_value); break; case BuiltinFnIdClz: - result = ir_build_clz(irb, scope, node, arg0_value, arg1_value); + result = ir_build_clz(ag, scope, node, arg0_value, arg1_value); break; case BuiltinFnIdBswap: - result = ir_build_bswap(irb, scope, node, arg0_value, arg1_value); + result = ir_build_bswap(ag, scope, node, arg0_value, arg1_value); break; case BuiltinFnIdBitReverse: - result = ir_build_bit_reverse(irb, scope, node, arg0_value, arg1_value); + result = ir_build_bit_reverse(ag, scope, node, arg0_value, arg1_value); break; default: zig_unreachable(); } - return ir_lval_wrap(irb, scope, result, lval, result_loc); + return ir_lval_wrap(ag, scope, result, lval, result_loc); } case BuiltinFnIdHasDecl: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) + IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; - IrInstSrc *has_decl = ir_build_has_decl(irb, scope, node, arg0_value, arg1_value); - return ir_lval_wrap(irb, scope, has_decl, lval, result_loc); + IrInstSrc *has_decl = ir_build_has_decl(ag, scope, node, arg0_value, arg1_value); + return ir_lval_wrap(ag, scope, has_decl, lval, result_loc); } case BuiltinFnIdUnionInit: { AstNode *union_type_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *union_type_inst = ir_gen_node(irb, union_type_node, scope); - if (union_type_inst == irb->codegen->invalid_inst_src) + IrInstSrc *union_type_inst = ir_gen_node(ag, union_type_node, scope); + if (union_type_inst == ag->codegen->invalid_inst_src) return union_type_inst; AstNode *name_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *name_inst = ir_gen_node(irb, name_node, scope); - if (name_inst == irb->codegen->invalid_inst_src) + IrInstSrc *name_inst = ir_gen_node(ag, name_node, scope); + if (name_inst == ag->codegen->invalid_inst_src) return name_inst; AstNode *init_node = node->data.fn_call_expr.params.at(2); - return ir_gen_union_init_expr(irb, scope, node, union_type_inst, name_inst, init_node, + return ir_gen_union_init_expr(ag, scope, node, union_type_inst, name_inst, init_node, lval, result_loc); } case BuiltinFnIdSrc: { - IrInstSrc *src_inst = ir_build_src(irb, scope, node); - return ir_lval_wrap(irb, scope, src_inst, lval, result_loc); + IrInstSrc *src_inst = ir_build_src(ag, scope, node); + return ir_lval_wrap(ag, scope, src_inst, lval, result_loc); } } zig_unreachable(); @@ -5339,13 +5339,13 @@ static ScopeNoSuspend *get_scope_nosuspend(Scope *scope) { return nullptr; } -static IrInstSrc *ir_gen_fn_call(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, +static IrInstSrc *ir_gen_fn_call(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypeFnCallExpr); if (node->data.fn_call_expr.modifier == CallModifierBuiltin) - return ir_gen_builtin_fn_call(irb, scope, node, lval, result_loc); + return ir_gen_builtin_fn_call(ag, scope, node, lval, result_loc); bool is_nosuspend = get_scope_nosuspend(scope) != nullptr; CallModifier modifier = node->data.fn_call_expr.modifier; @@ -5354,64 +5354,64 @@ static IrInstSrc *ir_gen_fn_call(IrBuilderSrc *irb, Scope *scope, AstNode *node, } AstNode *fn_ref_node = node->data.fn_call_expr.fn_ref_expr; - return ir_gen_fn_call_with_args(irb, scope, node, fn_ref_node, modifier, + return ir_gen_fn_call_with_args(ag, scope, node, fn_ref_node, modifier, nullptr, node->data.fn_call_expr.params.items, node->data.fn_call_expr.params.length, lval, result_loc); } -static IrInstSrc *ir_gen_if_bool_expr(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, +static IrInstSrc *ir_gen_if_bool_expr(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypeIfBoolExpr); - IrInstSrc *condition = ir_gen_node(irb, node->data.if_bool_expr.condition, scope); - if (condition == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; + IrInstSrc *condition = ir_gen_node(ag, node->data.if_bool_expr.condition, scope); + if (condition == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; IrInstSrc *is_comptime; - if (ir_should_inline(irb->exec, scope)) { - is_comptime = ir_build_const_bool(irb, scope, node, true); + if (ir_should_inline(ag->exec, scope)) { + is_comptime = ir_build_const_bool(ag, scope, node, true); } else { - is_comptime = ir_build_test_comptime(irb, scope, node, condition); + is_comptime = ir_build_test_comptime(ag, scope, node, condition); } AstNode *then_node = node->data.if_bool_expr.then_block; AstNode *else_node = node->data.if_bool_expr.else_node; - IrBasicBlockSrc *then_block = ir_create_basic_block(irb, scope, "Then"); - IrBasicBlockSrc *else_block = ir_create_basic_block(irb, scope, "Else"); - IrBasicBlockSrc *endif_block = ir_create_basic_block(irb, scope, "EndIf"); + IrBasicBlockSrc *then_block = ir_create_basic_block(ag, scope, "Then"); + IrBasicBlockSrc *else_block = ir_create_basic_block(ag, scope, "Else"); + IrBasicBlockSrc *endif_block = ir_create_basic_block(ag, scope, "EndIf"); - IrInstSrc *cond_br_inst = ir_build_cond_br(irb, scope, node, condition, + IrInstSrc *cond_br_inst = ir_build_cond_br(ag, scope, node, condition, then_block, else_block, is_comptime); - ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, else_block, endif_block, + ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(ag, cond_br_inst, else_block, endif_block, result_loc, is_comptime); - ir_set_cursor_at_end_and_append_block(irb, then_block); + ir_set_cursor_at_end_and_append_block(ag, then_block); - Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime); - IrInstSrc *then_expr_result = ir_gen_node_extra(irb, then_node, subexpr_scope, lval, + Scope *subexpr_scope = create_runtime_scope(ag->codegen, node, scope, is_comptime); + IrInstSrc *then_expr_result = ir_gen_node_extra(ag, then_node, subexpr_scope, lval, &peer_parent->peers.at(0)->base); - if (then_expr_result == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - IrBasicBlockSrc *after_then_block = irb->current_basic_block; + if (then_expr_result == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; + IrBasicBlockSrc *after_then_block = ag->current_basic_block; if (!instr_is_unreachable(then_expr_result)) - ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime)); + ir_mark_gen(ir_build_br(ag, scope, node, endif_block, is_comptime)); - ir_set_cursor_at_end_and_append_block(irb, else_block); + ir_set_cursor_at_end_and_append_block(ag, else_block); IrInstSrc *else_expr_result; if (else_node) { - else_expr_result = ir_gen_node_extra(irb, else_node, subexpr_scope, lval, &peer_parent->peers.at(1)->base); - if (else_expr_result == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; + else_expr_result = ir_gen_node_extra(ag, else_node, subexpr_scope, lval, &peer_parent->peers.at(1)->base); + if (else_expr_result == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; } else { - else_expr_result = ir_build_const_void(irb, scope, node); - ir_build_end_expr(irb, scope, node, else_expr_result, &peer_parent->peers.at(1)->base); + else_expr_result = ir_build_const_void(ag, scope, node); + ir_build_end_expr(ag, scope, node, else_expr_result, &peer_parent->peers.at(1)->base); } - IrBasicBlockSrc *after_else_block = irb->current_basic_block; + IrBasicBlockSrc *after_else_block = ag->current_basic_block; if (!instr_is_unreachable(else_expr_result)) - ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime)); + ir_mark_gen(ir_build_br(ag, scope, node, endif_block, is_comptime)); - ir_set_cursor_at_end_and_append_block(irb, endif_block); + ir_set_cursor_at_end_and_append_block(ag, endif_block); IrInstSrc **incoming_values = heap::c_allocator.allocate(2); incoming_values[0] = then_expr_result; incoming_values[1] = else_expr_result; @@ -5419,37 +5419,37 @@ static IrInstSrc *ir_gen_if_bool_expr(IrBuilderSrc *irb, Scope *scope, AstNode * incoming_blocks[0] = after_then_block; incoming_blocks[1] = after_else_block; - IrInstSrc *phi = ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, peer_parent); - return ir_expr_wrap(irb, scope, phi, result_loc); + IrInstSrc *phi = ir_build_phi(ag, scope, node, 2, incoming_blocks, incoming_values, peer_parent); + return ir_expr_wrap(ag, scope, phi, result_loc); } -static IrInstSrc *ir_gen_prefix_op_id_lval(IrBuilderSrc *irb, Scope *scope, AstNode *node, IrUnOp op_id, LVal lval) { +static IrInstSrc *ir_gen_prefix_op_id_lval(Stage1AstGen *ag, Scope *scope, AstNode *node, IrUnOp op_id, LVal lval) { assert(node->type == NodeTypePrefixOpExpr); AstNode *expr_node = node->data.prefix_op_expr.primary_expr; - IrInstSrc *value = ir_gen_node_extra(irb, expr_node, scope, lval, nullptr); - if (value == irb->codegen->invalid_inst_src) + IrInstSrc *value = ir_gen_node_extra(ag, expr_node, scope, lval, nullptr); + if (value == ag->codegen->invalid_inst_src) return value; - return ir_build_un_op(irb, scope, node, op_id, value); + return ir_build_un_op(ag, scope, node, op_id, value); } -static IrInstSrc *ir_gen_prefix_op_id(IrBuilderSrc *irb, Scope *scope, AstNode *node, IrUnOp op_id) { - return ir_gen_prefix_op_id_lval(irb, scope, node, op_id, LValNone); +static IrInstSrc *ir_gen_prefix_op_id(Stage1AstGen *ag, Scope *scope, AstNode *node, IrUnOp op_id) { + return ir_gen_prefix_op_id_lval(ag, scope, node, op_id, LValNone); } -static IrInstSrc *ir_expr_wrap(IrBuilderSrc *irb, Scope *scope, IrInstSrc *inst, ResultLoc *result_loc) { - if (inst == irb->codegen->invalid_inst_src) return inst; - ir_build_end_expr(irb, scope, inst->base.source_node, inst, result_loc); +static IrInstSrc *ir_expr_wrap(Stage1AstGen *ag, Scope *scope, IrInstSrc *inst, ResultLoc *result_loc) { + if (inst == ag->codegen->invalid_inst_src) return inst; + ir_build_end_expr(ag, scope, inst->base.source_node, inst, result_loc); return inst; } -static IrInstSrc *ir_lval_wrap(IrBuilderSrc *irb, Scope *scope, IrInstSrc *value, LVal lval, +static IrInstSrc *ir_lval_wrap(Stage1AstGen *ag, Scope *scope, IrInstSrc *value, LVal lval, ResultLoc *result_loc) { // This logic must be kept in sync with // [STMT_EXPR_TEST_THING] <--- (search this token) - if (value == irb->codegen->invalid_inst_src || + if (value == ag->codegen->invalid_inst_src || instr_is_unreachable(value) || value->base.source_node->type == NodeTypeDefer || value->id == IrInstSrcIdDeclVar) @@ -5461,9 +5461,9 @@ static IrInstSrc *ir_lval_wrap(IrBuilderSrc *irb, Scope *scope, IrInstSrc *value if (lval == LValPtr) { // We needed a pointer to a value, but we got a value. So we create // an instruction which just makes a pointer of it. - return ir_build_ref_src(irb, scope, value->base.source_node, value); + return ir_build_ref_src(ag, scope, value->base.source_node, value); } else if (result_loc != nullptr) { - return ir_expr_wrap(irb, scope, value, result_loc); + return ir_expr_wrap(ag, scope, value, result_loc); } else { return value; } @@ -5484,7 +5484,7 @@ static PtrLen star_token_to_ptr_len(TokenId token_id) { } } -static Error token_number_literal_u32(IrBuilderSrc *irb, AstNode *source_node, +static Error token_number_literal_u32(Stage1AstGen *ag, AstNode *source_node, RootStruct *root_struct, uint32_t *result, TokenIndex token) { BigInt bigint; @@ -5493,7 +5493,7 @@ static Error token_number_literal_u32(IrBuilderSrc *irb, AstNode *source_node, if (!bigint_fits_in_bits(&bigint, 32, false)) { Buf *val_buf = buf_alloc(); bigint_append_buf(val_buf, &bigint, 10); - exec_add_error_node(irb->codegen, irb->exec, source_node, + exec_add_error_node(ag->codegen, ag->exec, source_node, buf_sprintf("value %s too large for u32", buf_ptr(val_buf))); bigint_deinit(&bigint); return ErrorSemanticAnalyzeFail; @@ -5504,7 +5504,7 @@ static Error token_number_literal_u32(IrBuilderSrc *irb, AstNode *source_node, } -static IrInstSrc *ir_gen_pointer_type(IrBuilderSrc *irb, Scope *scope, AstNode *node) { +static IrInstSrc *ir_gen_pointer_type(Stage1AstGen *ag, Scope *scope, AstNode *node) { Error err; assert(node->type == NodeTypePointerType); @@ -5521,8 +5521,8 @@ static IrInstSrc *ir_gen_pointer_type(IrBuilderSrc *irb, Scope *scope, AstNode * IrInstSrc *sentinel; if (sentinel_expr != nullptr) { - sentinel = ir_gen_node(irb, sentinel_expr, scope); - if (sentinel == irb->codegen->invalid_inst_src) + sentinel = ir_gen_node(ag, sentinel_expr, scope); + if (sentinel == ag->codegen->invalid_inst_src) return sentinel; } else { sentinel = nullptr; @@ -5530,75 +5530,75 @@ static IrInstSrc *ir_gen_pointer_type(IrBuilderSrc *irb, Scope *scope, AstNode * IrInstSrc *align_value; if (align_expr != nullptr) { - align_value = ir_gen_node(irb, align_expr, scope); - if (align_value == irb->codegen->invalid_inst_src) + align_value = ir_gen_node(ag, align_expr, scope); + if (align_value == ag->codegen->invalid_inst_src) return align_value; } else { align_value = nullptr; } - IrInstSrc *child_type = ir_gen_node(irb, expr_node, scope); - if (child_type == irb->codegen->invalid_inst_src) + IrInstSrc *child_type = ir_gen_node(ag, expr_node, scope); + if (child_type == ag->codegen->invalid_inst_src) return child_type; uint32_t bit_offset_start = 0; if (node->data.pointer_type.bit_offset_start != 0) { - if ((err = token_number_literal_u32(irb, node, root_struct, &bit_offset_start, + if ((err = token_number_literal_u32(ag, node, root_struct, &bit_offset_start, node->data.pointer_type.bit_offset_start))) { - return irb->codegen->invalid_inst_src; + return ag->codegen->invalid_inst_src; } } uint32_t host_int_bytes = 0; if (node->data.pointer_type.host_int_bytes != 0) { - if ((err = token_number_literal_u32(irb, node, root_struct, &host_int_bytes, + if ((err = token_number_literal_u32(ag, node, root_struct, &host_int_bytes, node->data.pointer_type.host_int_bytes))) { - return irb->codegen->invalid_inst_src; + return ag->codegen->invalid_inst_src; } } if (host_int_bytes != 0 && bit_offset_start >= host_int_bytes * 8) { - exec_add_error_node(irb->codegen, irb->exec, node, + exec_add_error_node(ag->codegen, ag->exec, node, buf_sprintf("bit offset starts after end of host integer")); - return irb->codegen->invalid_inst_src; + return ag->codegen->invalid_inst_src; } - return ir_build_ptr_type(irb, scope, node, child_type, is_const, is_volatile, + return ir_build_ptr_type(ag, scope, node, child_type, is_const, is_volatile, ptr_len, sentinel, align_value, bit_offset_start, host_int_bytes, is_allow_zero); } -static IrInstSrc *ir_gen_catch_unreachable(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_gen_catch_unreachable(Stage1AstGen *ag, Scope *scope, AstNode *source_node, AstNode *expr_node, LVal lval, ResultLoc *result_loc) { - IrInstSrc *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr); - if (err_union_ptr == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; + IrInstSrc *err_union_ptr = ir_gen_node_extra(ag, expr_node, scope, LValPtr, nullptr); + if (err_union_ptr == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; - IrInstSrc *payload_ptr = ir_build_unwrap_err_payload_src(irb, scope, source_node, err_union_ptr, true, false); - if (payload_ptr == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; + IrInstSrc *payload_ptr = ir_build_unwrap_err_payload_src(ag, scope, source_node, err_union_ptr, true, false); + if (payload_ptr == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; if (lval == LValPtr) return payload_ptr; - IrInstSrc *load_ptr = ir_build_load_ptr(irb, scope, source_node, payload_ptr); - return ir_expr_wrap(irb, scope, load_ptr, result_loc); + IrInstSrc *load_ptr = ir_build_load_ptr(ag, scope, source_node, payload_ptr); + return ir_expr_wrap(ag, scope, load_ptr, result_loc); } -static IrInstSrc *ir_gen_bool_not(IrBuilderSrc *irb, Scope *scope, AstNode *node) { +static IrInstSrc *ir_gen_bool_not(Stage1AstGen *ag, Scope *scope, AstNode *node) { assert(node->type == NodeTypePrefixOpExpr); AstNode *expr_node = node->data.prefix_op_expr.primary_expr; - IrInstSrc *value = ir_gen_node(irb, expr_node, scope); - if (value == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; + IrInstSrc *value = ir_gen_node(ag, expr_node, scope); + if (value == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; - return ir_build_bool_not(irb, scope, node, value); + return ir_build_bool_not(ag, scope, node, value); } -static IrInstSrc *ir_gen_prefix_op_expr(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, +static IrInstSrc *ir_gen_prefix_op_expr(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypePrefixOpExpr); @@ -5609,49 +5609,49 @@ static IrInstSrc *ir_gen_prefix_op_expr(IrBuilderSrc *irb, Scope *scope, AstNode case PrefixOpInvalid: zig_unreachable(); case PrefixOpBoolNot: - return ir_lval_wrap(irb, scope, ir_gen_bool_not(irb, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_bool_not(ag, scope, node), lval, result_loc); case PrefixOpBinNot: - return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpBinNot), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_prefix_op_id(ag, scope, node, IrUnOpBinNot), lval, result_loc); case PrefixOpNegation: - return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegation), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_prefix_op_id(ag, scope, node, IrUnOpNegation), lval, result_loc); case PrefixOpNegationWrap: - return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegationWrap), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_prefix_op_id(ag, scope, node, IrUnOpNegationWrap), lval, result_loc); case PrefixOpOptional: - return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpOptional), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_prefix_op_id(ag, scope, node, IrUnOpOptional), lval, result_loc); case PrefixOpAddrOf: { AstNode *expr_node = node->data.prefix_op_expr.primary_expr; - return ir_lval_wrap(irb, scope, ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_node_extra(ag, expr_node, scope, LValPtr, nullptr), lval, result_loc); } } zig_unreachable(); } -static IrInstSrc *ir_gen_union_init_expr(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_gen_union_init_expr(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *union_type, IrInstSrc *field_name, AstNode *expr_node, LVal lval, ResultLoc *parent_result_loc) { - IrInstSrc *container_ptr = ir_build_resolve_result(irb, scope, source_node, parent_result_loc, union_type); - IrInstSrc *field_ptr = ir_build_field_ptr_instruction(irb, scope, source_node, container_ptr, + IrInstSrc *container_ptr = ir_build_resolve_result(ag, scope, source_node, parent_result_loc, union_type); + IrInstSrc *field_ptr = ir_build_field_ptr_instruction(ag, scope, source_node, container_ptr, field_name, true); ResultLocInstruction *result_loc_inst = heap::c_allocator.create(); result_loc_inst->base.id = ResultLocIdInstruction; result_loc_inst->base.source_instruction = field_ptr; - ir_ref_instruction(field_ptr, irb->current_basic_block); - ir_build_reset_result(irb, scope, expr_node, &result_loc_inst->base); + ir_ref_instruction(field_ptr, ag->current_basic_block); + ir_build_reset_result(ag, scope, expr_node, &result_loc_inst->base); - IrInstSrc *expr_value = ir_gen_node_extra(irb, expr_node, scope, LValNone, + IrInstSrc *expr_value = ir_gen_node_extra(ag, expr_node, scope, LValNone, &result_loc_inst->base); - if (expr_value == irb->codegen->invalid_inst_src) + if (expr_value == ag->codegen->invalid_inst_src) return expr_value; - IrInstSrc *init_union = ir_build_union_init_named_field(irb, scope, source_node, union_type, + IrInstSrc *init_union = ir_build_union_init_named_field(ag, scope, source_node, union_type, field_name, field_ptr, container_ptr); - return ir_lval_wrap(irb, scope, init_union, lval, parent_result_loc); + return ir_lval_wrap(ag, scope, init_union, lval, parent_result_loc); } -static IrInstSrc *ir_gen_container_init_expr(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, +static IrInstSrc *ir_gen_container_init_expr(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, ResultLoc *parent_result_loc) { assert(node->type == NodeTypeContainerInitExpr); @@ -5666,33 +5666,33 @@ static IrInstSrc *ir_gen_container_init_expr(IrBuilderSrc *irb, Scope *scope, As IrInstSrc *container_type; if (container_init_expr->type->type == NodeTypeInferredArrayType) { if (kind == ContainerInitKindStruct) { - add_node_error(irb->codegen, container_init_expr->type, + add_node_error(ag->codegen, container_init_expr->type, buf_sprintf("initializing array with struct syntax")); - return irb->codegen->invalid_inst_src; + return ag->codegen->invalid_inst_src; } IrInstSrc *sentinel; if (container_init_expr->type->data.inferred_array_type.sentinel != nullptr) { - sentinel = ir_gen_node(irb, container_init_expr->type->data.inferred_array_type.sentinel, scope); - if (sentinel == irb->codegen->invalid_inst_src) + sentinel = ir_gen_node(ag, container_init_expr->type->data.inferred_array_type.sentinel, scope); + if (sentinel == ag->codegen->invalid_inst_src) return sentinel; } else { sentinel = nullptr; } - IrInstSrc *elem_type = ir_gen_node(irb, + IrInstSrc *elem_type = ir_gen_node(ag, container_init_expr->type->data.inferred_array_type.child_type, scope); - if (elem_type == irb->codegen->invalid_inst_src) + if (elem_type == ag->codegen->invalid_inst_src) return elem_type; size_t item_count = container_init_expr->entries.length; - IrInstSrc *item_count_inst = ir_build_const_usize(irb, scope, node, item_count); - container_type = ir_build_array_type(irb, scope, node, item_count_inst, sentinel, elem_type); + IrInstSrc *item_count_inst = ir_build_const_usize(ag, scope, node, item_count); + container_type = ir_build_array_type(ag, scope, node, item_count_inst, sentinel, elem_type); } else { - container_type = ir_gen_node(irb, container_init_expr->type, scope); - if (container_type == irb->codegen->invalid_inst_src) + container_type = ir_gen_node(ag, container_init_expr->type, scope); + if (container_type == ag->codegen->invalid_inst_src) return container_type; } - result_loc_cast = ir_build_cast_result_loc(irb, container_type, parent_result_loc); + result_loc_cast = ir_build_cast_result_loc(ag, container_type, parent_result_loc); child_result_loc = &result_loc_cast->base; init_array_type_source_node = container_type->base.source_node; } else { @@ -5706,7 +5706,7 @@ static IrInstSrc *ir_gen_container_init_expr(IrBuilderSrc *irb, Scope *scope, As switch (kind) { case ContainerInitKindStruct: { - IrInstSrc *container_ptr = ir_build_resolve_result(irb, scope, node, child_result_loc, + IrInstSrc *container_ptr = ir_build_resolve_result(ag, scope, node, child_result_loc, nullptr); size_t field_count = container_init_expr->entries.length; @@ -5718,122 +5718,122 @@ static IrInstSrc *ir_gen_container_init_expr(IrBuilderSrc *irb, Scope *scope, As Buf *name = entry_node->data.struct_val_field.name; AstNode *expr_node = entry_node->data.struct_val_field.expr; - IrInstSrc *field_ptr = ir_build_field_ptr(irb, scope, entry_node, container_ptr, name, true); + IrInstSrc *field_ptr = ir_build_field_ptr(ag, scope, entry_node, container_ptr, name, true); ResultLocInstruction *result_loc_inst = heap::c_allocator.create(); result_loc_inst->base.id = ResultLocIdInstruction; result_loc_inst->base.source_instruction = field_ptr; result_loc_inst->base.allow_write_through_const = true; - ir_ref_instruction(field_ptr, irb->current_basic_block); - ir_build_reset_result(irb, scope, expr_node, &result_loc_inst->base); + ir_ref_instruction(field_ptr, ag->current_basic_block); + ir_build_reset_result(ag, scope, expr_node, &result_loc_inst->base); - IrInstSrc *expr_value = ir_gen_node_extra(irb, expr_node, scope, LValNone, + IrInstSrc *expr_value = ir_gen_node_extra(ag, expr_node, scope, LValNone, &result_loc_inst->base); - if (expr_value == irb->codegen->invalid_inst_src) + if (expr_value == ag->codegen->invalid_inst_src) return expr_value; fields[i].name = name; fields[i].source_node = entry_node; fields[i].result_loc = field_ptr; } - IrInstSrc *result = ir_build_container_init_fields(irb, scope, node, field_count, + IrInstSrc *result = ir_build_container_init_fields(ag, scope, node, field_count, fields, container_ptr); if (result_loc_cast != nullptr) { - result = ir_build_implicit_cast(irb, scope, node, result, result_loc_cast); + result = ir_build_implicit_cast(ag, scope, node, result, result_loc_cast); } - return ir_lval_wrap(irb, scope, result, lval, parent_result_loc); + return ir_lval_wrap(ag, scope, result, lval, parent_result_loc); } case ContainerInitKindArray: { size_t item_count = container_init_expr->entries.length; - IrInstSrc *container_ptr = ir_build_resolve_result(irb, scope, node, child_result_loc, + IrInstSrc *container_ptr = ir_build_resolve_result(ag, scope, node, child_result_loc, nullptr); IrInstSrc **result_locs = heap::c_allocator.allocate(item_count); for (size_t i = 0; i < item_count; i += 1) { AstNode *expr_node = container_init_expr->entries.at(i); - IrInstSrc *elem_index = ir_build_const_usize(irb, scope, expr_node, i); - IrInstSrc *elem_ptr = ir_build_elem_ptr(irb, scope, expr_node, container_ptr, + IrInstSrc *elem_index = ir_build_const_usize(ag, scope, expr_node, i); + IrInstSrc *elem_ptr = ir_build_elem_ptr(ag, scope, expr_node, container_ptr, elem_index, false, PtrLenSingle, init_array_type_source_node); ResultLocInstruction *result_loc_inst = heap::c_allocator.create(); result_loc_inst->base.id = ResultLocIdInstruction; result_loc_inst->base.source_instruction = elem_ptr; result_loc_inst->base.allow_write_through_const = true; - ir_ref_instruction(elem_ptr, irb->current_basic_block); - ir_build_reset_result(irb, scope, expr_node, &result_loc_inst->base); + ir_ref_instruction(elem_ptr, ag->current_basic_block); + ir_build_reset_result(ag, scope, expr_node, &result_loc_inst->base); - IrInstSrc *expr_value = ir_gen_node_extra(irb, expr_node, scope, LValNone, + IrInstSrc *expr_value = ir_gen_node_extra(ag, expr_node, scope, LValNone, &result_loc_inst->base); - if (expr_value == irb->codegen->invalid_inst_src) + if (expr_value == ag->codegen->invalid_inst_src) return expr_value; result_locs[i] = elem_ptr; } - IrInstSrc *result = ir_build_container_init_list(irb, scope, node, item_count, + IrInstSrc *result = ir_build_container_init_list(ag, scope, node, item_count, result_locs, container_ptr, init_array_type_source_node); if (result_loc_cast != nullptr) { - result = ir_build_implicit_cast(irb, scope, node, result, result_loc_cast); + result = ir_build_implicit_cast(ag, scope, node, result, result_loc_cast); } - return ir_lval_wrap(irb, scope, result, lval, parent_result_loc); + return ir_lval_wrap(ag, scope, result, lval, parent_result_loc); } } zig_unreachable(); } -static ResultLocVar *ir_build_var_result_loc(IrBuilderSrc *irb, IrInstSrc *alloca, ZigVar *var) { +static ResultLocVar *ir_build_var_result_loc(Stage1AstGen *ag, IrInstSrc *alloca, ZigVar *var) { ResultLocVar *result_loc_var = heap::c_allocator.create(); result_loc_var->base.id = ResultLocIdVar; result_loc_var->base.source_instruction = alloca; result_loc_var->base.allow_write_through_const = true; result_loc_var->var = var; - ir_build_reset_result(irb, alloca->base.scope, alloca->base.source_node, &result_loc_var->base); + ir_build_reset_result(ag, alloca->base.scope, alloca->base.source_node, &result_loc_var->base); return result_loc_var; } -static ResultLocCast *ir_build_cast_result_loc(IrBuilderSrc *irb, IrInstSrc *dest_type, +static ResultLocCast *ir_build_cast_result_loc(Stage1AstGen *ag, IrInstSrc *dest_type, ResultLoc *parent_result_loc) { ResultLocCast *result_loc_cast = heap::c_allocator.create(); result_loc_cast->base.id = ResultLocIdCast; result_loc_cast->base.source_instruction = dest_type; result_loc_cast->base.allow_write_through_const = parent_result_loc->allow_write_through_const; - ir_ref_instruction(dest_type, irb->current_basic_block); + ir_ref_instruction(dest_type, ag->current_basic_block); result_loc_cast->parent = parent_result_loc; - ir_build_reset_result(irb, dest_type->base.scope, dest_type->base.source_node, &result_loc_cast->base); + ir_build_reset_result(ag, dest_type->base.scope, dest_type->base.source_node, &result_loc_cast->base); return result_loc_cast; } -static void build_decl_var_and_init(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, ZigVar *var, +static void build_decl_var_and_init(Stage1AstGen *ag, Scope *scope, AstNode *source_node, ZigVar *var, IrInstSrc *init, const char *name_hint, IrInstSrc *is_comptime) { - IrInstSrc *alloca = ir_build_alloca_src(irb, scope, source_node, nullptr, name_hint, is_comptime); - ResultLocVar *var_result_loc = ir_build_var_result_loc(irb, alloca, var); - ir_build_end_expr(irb, scope, source_node, init, &var_result_loc->base); - ir_build_var_decl_src(irb, scope, source_node, var, nullptr, alloca); + IrInstSrc *alloca = ir_build_alloca_src(ag, scope, source_node, nullptr, name_hint, is_comptime); + ResultLocVar *var_result_loc = ir_build_var_result_loc(ag, alloca, var); + ir_build_end_expr(ag, scope, source_node, init, &var_result_loc->base); + ir_build_var_decl_src(ag, scope, source_node, var, nullptr, alloca); } -static IrInstSrc *ir_gen_var_decl(IrBuilderSrc *irb, Scope *scope, AstNode *node) { +static IrInstSrc *ir_gen_var_decl(Stage1AstGen *ag, Scope *scope, AstNode *node) { assert(node->type == NodeTypeVariableDeclaration); AstNodeVariableDeclaration *variable_declaration = &node->data.variable_declaration; if (buf_eql_str(variable_declaration->symbol, "_")) { - add_node_error(irb->codegen, node, buf_sprintf("`_` is not a declarable symbol")); - return irb->codegen->invalid_inst_src; + add_node_error(ag->codegen, node, buf_sprintf("`_` is not a declarable symbol")); + return ag->codegen->invalid_inst_src; } // Used for the type expr and the align expr - Scope *comptime_scope = create_comptime_scope(irb->codegen, node, scope); + Scope *comptime_scope = create_comptime_scope(ag->codegen, node, scope); IrInstSrc *type_instruction; if (variable_declaration->type != nullptr) { - type_instruction = ir_gen_node(irb, variable_declaration->type, comptime_scope); - if (type_instruction == irb->codegen->invalid_inst_src) + type_instruction = ir_gen_node(ag, variable_declaration->type, comptime_scope); + if (type_instruction == ag->codegen->invalid_inst_src) return type_instruction; } else { type_instruction = nullptr; @@ -5843,43 +5843,43 @@ static IrInstSrc *ir_gen_var_decl(IrBuilderSrc *irb, Scope *scope, AstNode *node bool is_const = variable_declaration->is_const; bool is_extern = variable_declaration->is_extern; - bool is_comptime_scalar = ir_should_inline(irb->exec, scope) || variable_declaration->is_comptime; - IrInstSrc *is_comptime = ir_build_const_bool(irb, scope, node, is_comptime_scalar); - ZigVar *var = ir_create_var(irb, node, scope, variable_declaration->symbol, + bool is_comptime_scalar = ir_should_inline(ag->exec, scope) || variable_declaration->is_comptime; + IrInstSrc *is_comptime = ir_build_const_bool(ag, scope, node, is_comptime_scalar); + ZigVar *var = ir_create_var(ag, node, scope, variable_declaration->symbol, is_const, is_const, is_shadowable, is_comptime); // we detect IrInstSrcDeclVar in gen_block to make sure the next node // is inside var->child_scope if (!is_extern && !variable_declaration->expr) { - var->var_type = irb->codegen->builtin_types.entry_invalid; - add_node_error(irb->codegen, node, buf_sprintf("variables must be initialized")); - return irb->codegen->invalid_inst_src; + var->var_type = ag->codegen->builtin_types.entry_invalid; + add_node_error(ag->codegen, node, buf_sprintf("variables must be initialized")); + return ag->codegen->invalid_inst_src; } IrInstSrc *align_value = nullptr; if (variable_declaration->align_expr != nullptr) { - align_value = ir_gen_node(irb, variable_declaration->align_expr, comptime_scope); - if (align_value == irb->codegen->invalid_inst_src) + align_value = ir_gen_node(ag, variable_declaration->align_expr, comptime_scope); + if (align_value == ag->codegen->invalid_inst_src) return align_value; } if (variable_declaration->section_expr != nullptr) { - add_node_error(irb->codegen, variable_declaration->section_expr, + add_node_error(ag->codegen, variable_declaration->section_expr, buf_sprintf("cannot set section of local variable '%s'", buf_ptr(variable_declaration->symbol))); } // Parser should ensure that this never happens assert(variable_declaration->threadlocal_tok == 0); - IrInstSrc *alloca = ir_build_alloca_src(irb, scope, node, align_value, + IrInstSrc *alloca = ir_build_alloca_src(ag, scope, node, align_value, buf_ptr(variable_declaration->symbol), is_comptime); // Create a result location for the initialization expression. - ResultLocVar *result_loc_var = ir_build_var_result_loc(irb, alloca, var); + ResultLocVar *result_loc_var = ir_build_var_result_loc(ag, alloca, var); ResultLoc *init_result_loc; ResultLocCast *result_loc_cast; if (type_instruction != nullptr) { - result_loc_cast = ir_build_cast_result_loc(irb, type_instruction, &result_loc_var->base); + result_loc_cast = ir_build_cast_result_loc(ag, type_instruction, &result_loc_var->base); init_result_loc = &result_loc_cast->base; } else { result_loc_cast = nullptr; @@ -5887,29 +5887,29 @@ static IrInstSrc *ir_gen_var_decl(IrBuilderSrc *irb, Scope *scope, AstNode *node } Scope *init_scope = is_comptime_scalar ? - create_comptime_scope(irb->codegen, variable_declaration->expr, scope) : scope; + create_comptime_scope(ag->codegen, variable_declaration->expr, scope) : scope; // Temporarily set the name of the Stage1Zir to the VariableDeclaration // so that the struct or enum from the init expression inherits the name. - Buf *old_exec_name = irb->exec->name; - irb->exec->name = variable_declaration->symbol; - IrInstSrc *init_value = ir_gen_node_extra(irb, variable_declaration->expr, init_scope, + Buf *old_exec_name = ag->exec->name; + ag->exec->name = variable_declaration->symbol; + IrInstSrc *init_value = ir_gen_node_extra(ag, variable_declaration->expr, init_scope, LValNone, init_result_loc); - irb->exec->name = old_exec_name; + ag->exec->name = old_exec_name; - if (init_value == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; + if (init_value == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; if (result_loc_cast != nullptr) { - IrInstSrc *implicit_cast = ir_build_implicit_cast(irb, scope, init_value->base.source_node, + IrInstSrc *implicit_cast = ir_build_implicit_cast(ag, scope, init_value->base.source_node, init_value, result_loc_cast); - ir_build_end_expr(irb, scope, node, implicit_cast, &result_loc_var->base); + ir_build_end_expr(ag, scope, node, implicit_cast, &result_loc_var->base); } - return ir_build_var_decl_src(irb, scope, node, var, align_value, alloca); + return ir_build_var_decl_src(ag, scope, node, var, align_value, alloca); } -static IrInstSrc *ir_gen_while_expr(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, +static IrInstSrc *ir_gen_while_expr(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypeWhileExpr); @@ -5917,73 +5917,73 @@ static IrInstSrc *ir_gen_while_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no AstNode *continue_expr_node = node->data.while_expr.continue_expr; AstNode *else_node = node->data.while_expr.else_node; - IrBasicBlockSrc *cond_block = ir_create_basic_block(irb, scope, "WhileCond"); - IrBasicBlockSrc *body_block = ir_create_basic_block(irb, scope, "WhileBody"); + IrBasicBlockSrc *cond_block = ir_create_basic_block(ag, scope, "WhileCond"); + IrBasicBlockSrc *body_block = ir_create_basic_block(ag, scope, "WhileBody"); IrBasicBlockSrc *continue_block = continue_expr_node ? - ir_create_basic_block(irb, scope, "WhileContinue") : cond_block; - IrBasicBlockSrc *end_block = ir_create_basic_block(irb, scope, "WhileEnd"); + ir_create_basic_block(ag, scope, "WhileContinue") : cond_block; + IrBasicBlockSrc *end_block = ir_create_basic_block(ag, scope, "WhileEnd"); IrBasicBlockSrc *else_block = else_node ? - ir_create_basic_block(irb, scope, "WhileElse") : end_block; + ir_create_basic_block(ag, scope, "WhileElse") : end_block; - IrInstSrc *is_comptime = ir_build_const_bool(irb, scope, node, - ir_should_inline(irb->exec, scope) || node->data.while_expr.is_inline); - ir_build_br(irb, scope, node, cond_block, is_comptime); + IrInstSrc *is_comptime = ir_build_const_bool(ag, scope, node, + ir_should_inline(ag->exec, scope) || node->data.while_expr.is_inline); + ir_build_br(ag, scope, node, cond_block, is_comptime); - Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime); + Scope *subexpr_scope = create_runtime_scope(ag->codegen, node, scope, is_comptime); Buf *var_symbol = node->data.while_expr.var_symbol; Buf *err_symbol = node->data.while_expr.err_symbol; if (err_symbol != nullptr) { - ir_set_cursor_at_end_and_append_block(irb, cond_block); + ir_set_cursor_at_end_and_append_block(ag, cond_block); Scope *payload_scope; AstNode *symbol_node = node; // TODO make more accurate ZigVar *payload_var; if (var_symbol) { // TODO make it an error to write to payload variable - payload_var = ir_create_var(irb, symbol_node, subexpr_scope, var_symbol, + payload_var = ir_create_var(ag, symbol_node, subexpr_scope, var_symbol, true, false, false, is_comptime); payload_scope = payload_var->child_scope; } else { payload_scope = subexpr_scope; } - ScopeExpr *spill_scope = create_expr_scope(irb->codegen, node, payload_scope); - IrInstSrc *err_val_ptr = ir_gen_node_extra(irb, node->data.while_expr.condition, subexpr_scope, + ScopeExpr *spill_scope = create_expr_scope(ag->codegen, node, payload_scope); + IrInstSrc *err_val_ptr = ir_gen_node_extra(ag, node->data.while_expr.condition, subexpr_scope, LValPtr, nullptr); - if (err_val_ptr == irb->codegen->invalid_inst_src) + if (err_val_ptr == ag->codegen->invalid_inst_src) return err_val_ptr; - IrInstSrc *is_err = ir_build_test_err_src(irb, scope, node->data.while_expr.condition, err_val_ptr, + IrInstSrc *is_err = ir_build_test_err_src(ag, scope, node->data.while_expr.condition, err_val_ptr, true, false); - IrBasicBlockSrc *after_cond_block = irb->current_basic_block; - IrInstSrc *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, scope, node)); + IrBasicBlockSrc *after_cond_block = ag->current_basic_block; + IrInstSrc *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(ag, scope, node)); IrInstSrc *cond_br_inst; if (!instr_is_unreachable(is_err)) { - cond_br_inst = ir_build_cond_br(irb, scope, node->data.while_expr.condition, is_err, + cond_br_inst = ir_build_cond_br(ag, scope, node->data.while_expr.condition, is_err, else_block, body_block, is_comptime); cond_br_inst->is_gen = true; } else { // for the purposes of the source instruction to ir_build_result_peers - cond_br_inst = irb->current_basic_block->instruction_list.last(); + cond_br_inst = ag->current_basic_block->instruction_list.last(); } - ResultLocPeerParent *peer_parent = ir_build_result_peers(irb, cond_br_inst, end_block, result_loc, + ResultLocPeerParent *peer_parent = ir_build_result_peers(ag, cond_br_inst, end_block, result_loc, is_comptime); - ir_set_cursor_at_end_and_append_block(irb, body_block); + ir_set_cursor_at_end_and_append_block(ag, body_block); if (var_symbol) { - IrInstSrc *payload_ptr = ir_build_unwrap_err_payload_src(irb, &spill_scope->base, symbol_node, + IrInstSrc *payload_ptr = ir_build_unwrap_err_payload_src(ag, &spill_scope->base, symbol_node, err_val_ptr, false, false); IrInstSrc *var_value = node->data.while_expr.var_is_ptr ? - payload_ptr : ir_build_load_ptr(irb, &spill_scope->base, symbol_node, payload_ptr); - build_decl_var_and_init(irb, payload_scope, symbol_node, payload_var, var_value, buf_ptr(var_symbol), is_comptime); + payload_ptr : ir_build_load_ptr(ag, &spill_scope->base, symbol_node, payload_ptr); + build_decl_var_and_init(ag, payload_scope, symbol_node, payload_var, var_value, buf_ptr(var_symbol), is_comptime); } ZigList incoming_values = {0}; ZigList incoming_blocks = {0}; - if (is_duplicate_label(irb->codegen, payload_scope, node, node->data.while_expr.name)) - return irb->codegen->invalid_inst_src; + if (is_duplicate_label(ag->codegen, payload_scope, node, node->data.while_expr.name)) + return ag->codegen->invalid_inst_src; - ScopeLoop *loop_scope = create_loop_scope(irb->codegen, node, payload_scope); + ScopeLoop *loop_scope = create_loop_scope(ag->codegen, node, payload_scope); loop_scope->break_block = end_block; loop_scope->continue_block = continue_block; loop_scope->is_comptime = is_comptime; @@ -5996,54 +5996,54 @@ static IrInstSrc *ir_gen_while_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no // Note the body block of the loop is not the place that lval and result_loc are used - // it's actually in break statements, handled similarly to return statements. // That is why we set those values in loop_scope above and not in this ir_gen_node call. - IrInstSrc *body_result = ir_gen_node(irb, node->data.while_expr.body, &loop_scope->base); - if (body_result == irb->codegen->invalid_inst_src) + IrInstSrc *body_result = ir_gen_node(ag, node->data.while_expr.body, &loop_scope->base); + if (body_result == ag->codegen->invalid_inst_src) return body_result; if (loop_scope->name != nullptr && loop_scope->name_used == false) { - add_node_error(irb->codegen, node, buf_sprintf("unused while label")); + add_node_error(ag->codegen, node, buf_sprintf("unused while label")); } if (!instr_is_unreachable(body_result)) { - ir_mark_gen(ir_build_check_statement_is_void(irb, payload_scope, node->data.while_expr.body, body_result)); - ir_mark_gen(ir_build_br(irb, payload_scope, node, continue_block, is_comptime)); + ir_mark_gen(ir_build_check_statement_is_void(ag, payload_scope, node->data.while_expr.body, body_result)); + ir_mark_gen(ir_build_br(ag, payload_scope, node, continue_block, is_comptime)); } if (continue_expr_node) { - ir_set_cursor_at_end_and_append_block(irb, continue_block); - IrInstSrc *expr_result = ir_gen_node(irb, continue_expr_node, payload_scope); - if (expr_result == irb->codegen->invalid_inst_src) + ir_set_cursor_at_end_and_append_block(ag, continue_block); + IrInstSrc *expr_result = ir_gen_node(ag, continue_expr_node, payload_scope); + if (expr_result == ag->codegen->invalid_inst_src) return expr_result; if (!instr_is_unreachable(expr_result)) { - ir_mark_gen(ir_build_check_statement_is_void(irb, payload_scope, continue_expr_node, expr_result)); - ir_mark_gen(ir_build_br(irb, payload_scope, node, cond_block, is_comptime)); + ir_mark_gen(ir_build_check_statement_is_void(ag, payload_scope, continue_expr_node, expr_result)); + ir_mark_gen(ir_build_br(ag, payload_scope, node, cond_block, is_comptime)); } } - ir_set_cursor_at_end_and_append_block(irb, else_block); + ir_set_cursor_at_end_and_append_block(ag, else_block); assert(else_node != nullptr); // TODO make it an error to write to error variable AstNode *err_symbol_node = else_node; // TODO make more accurate - ZigVar *err_var = ir_create_var(irb, err_symbol_node, scope, err_symbol, + ZigVar *err_var = ir_create_var(ag, err_symbol_node, scope, err_symbol, true, false, false, is_comptime); Scope *err_scope = err_var->child_scope; - IrInstSrc *err_ptr = ir_build_unwrap_err_code_src(irb, err_scope, err_symbol_node, err_val_ptr); - IrInstSrc *err_value = ir_build_load_ptr(irb, err_scope, err_symbol_node, err_ptr); - build_decl_var_and_init(irb, err_scope, err_symbol_node, err_var, err_value, buf_ptr(err_symbol), is_comptime); + IrInstSrc *err_ptr = ir_build_unwrap_err_code_src(ag, err_scope, err_symbol_node, err_val_ptr); + IrInstSrc *err_value = ir_build_load_ptr(ag, err_scope, err_symbol_node, err_ptr); + build_decl_var_and_init(ag, err_scope, err_symbol_node, err_var, err_value, buf_ptr(err_symbol), is_comptime); if (peer_parent->peers.length != 0) { peer_parent->peers.last()->next_bb = else_block; } ResultLocPeer *peer_result = create_peer_result(peer_parent); peer_parent->peers.append(peer_result); - IrInstSrc *else_result = ir_gen_node_extra(irb, else_node, err_scope, lval, &peer_result->base); - if (else_result == irb->codegen->invalid_inst_src) + IrInstSrc *else_result = ir_gen_node_extra(ag, else_node, err_scope, lval, &peer_result->base); + if (else_result == ag->codegen->invalid_inst_src) return else_result; if (!instr_is_unreachable(else_result)) - ir_mark_gen(ir_build_br(irb, scope, node, end_block, is_comptime)); - IrBasicBlockSrc *after_else_block = irb->current_basic_block; - ir_set_cursor_at_end_and_append_block(irb, end_block); + ir_mark_gen(ir_build_br(ag, scope, node, end_block, is_comptime)); + IrBasicBlockSrc *after_else_block = ag->current_basic_block; + ir_set_cursor_at_end_and_append_block(ag, end_block); if (else_result) { incoming_blocks.append(after_else_block); incoming_values.append(else_result); @@ -6055,53 +6055,53 @@ static IrInstSrc *ir_gen_while_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no peer_parent->peers.last()->next_bb = end_block; } - IrInstSrc *phi = ir_build_phi(irb, scope, node, incoming_blocks.length, + IrInstSrc *phi = ir_build_phi(ag, scope, node, incoming_blocks.length, incoming_blocks.items, incoming_values.items, peer_parent); - return ir_expr_wrap(irb, scope, phi, result_loc); + return ir_expr_wrap(ag, scope, phi, result_loc); } else if (var_symbol != nullptr) { - ir_set_cursor_at_end_and_append_block(irb, cond_block); - Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime); + ir_set_cursor_at_end_and_append_block(ag, cond_block); + Scope *subexpr_scope = create_runtime_scope(ag->codegen, node, scope, is_comptime); // TODO make it an error to write to payload variable AstNode *symbol_node = node; // TODO make more accurate - ZigVar *payload_var = ir_create_var(irb, symbol_node, subexpr_scope, var_symbol, + ZigVar *payload_var = ir_create_var(ag, symbol_node, subexpr_scope, var_symbol, true, false, false, is_comptime); Scope *child_scope = payload_var->child_scope; - ScopeExpr *spill_scope = create_expr_scope(irb->codegen, node, child_scope); - IrInstSrc *maybe_val_ptr = ir_gen_node_extra(irb, node->data.while_expr.condition, subexpr_scope, + ScopeExpr *spill_scope = create_expr_scope(ag->codegen, node, child_scope); + IrInstSrc *maybe_val_ptr = ir_gen_node_extra(ag, node->data.while_expr.condition, subexpr_scope, LValPtr, nullptr); - if (maybe_val_ptr == irb->codegen->invalid_inst_src) + if (maybe_val_ptr == ag->codegen->invalid_inst_src) return maybe_val_ptr; - IrInstSrc *maybe_val = ir_build_load_ptr(irb, scope, node->data.while_expr.condition, maybe_val_ptr); - IrInstSrc *is_non_null = ir_build_test_non_null_src(irb, scope, node->data.while_expr.condition, maybe_val); - IrBasicBlockSrc *after_cond_block = irb->current_basic_block; - IrInstSrc *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, scope, node)); + IrInstSrc *maybe_val = ir_build_load_ptr(ag, scope, node->data.while_expr.condition, maybe_val_ptr); + IrInstSrc *is_non_null = ir_build_test_non_null_src(ag, scope, node->data.while_expr.condition, maybe_val); + IrBasicBlockSrc *after_cond_block = ag->current_basic_block; + IrInstSrc *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(ag, scope, node)); IrInstSrc *cond_br_inst; if (!instr_is_unreachable(is_non_null)) { - cond_br_inst = ir_build_cond_br(irb, scope, node->data.while_expr.condition, is_non_null, + cond_br_inst = ir_build_cond_br(ag, scope, node->data.while_expr.condition, is_non_null, body_block, else_block, is_comptime); cond_br_inst->is_gen = true; } else { // for the purposes of the source instruction to ir_build_result_peers - cond_br_inst = irb->current_basic_block->instruction_list.last(); + cond_br_inst = ag->current_basic_block->instruction_list.last(); } - ResultLocPeerParent *peer_parent = ir_build_result_peers(irb, cond_br_inst, end_block, result_loc, + ResultLocPeerParent *peer_parent = ir_build_result_peers(ag, cond_br_inst, end_block, result_loc, is_comptime); - ir_set_cursor_at_end_and_append_block(irb, body_block); - IrInstSrc *payload_ptr = ir_build_optional_unwrap_ptr(irb, &spill_scope->base, symbol_node, maybe_val_ptr, false); + ir_set_cursor_at_end_and_append_block(ag, body_block); + IrInstSrc *payload_ptr = ir_build_optional_unwrap_ptr(ag, &spill_scope->base, symbol_node, maybe_val_ptr, false); IrInstSrc *var_value = node->data.while_expr.var_is_ptr ? - payload_ptr : ir_build_load_ptr(irb, &spill_scope->base, symbol_node, payload_ptr); - build_decl_var_and_init(irb, child_scope, symbol_node, payload_var, var_value, buf_ptr(var_symbol), is_comptime); + payload_ptr : ir_build_load_ptr(ag, &spill_scope->base, symbol_node, payload_ptr); + build_decl_var_and_init(ag, child_scope, symbol_node, payload_var, var_value, buf_ptr(var_symbol), is_comptime); ZigList incoming_values = {0}; ZigList incoming_blocks = {0}; - if (is_duplicate_label(irb->codegen, child_scope, node, node->data.while_expr.name)) - return irb->codegen->invalid_inst_src; + if (is_duplicate_label(ag->codegen, child_scope, node, node->data.while_expr.name)) + return ag->codegen->invalid_inst_src; - ScopeLoop *loop_scope = create_loop_scope(irb->codegen, node, child_scope); + ScopeLoop *loop_scope = create_loop_scope(ag->codegen, node, child_scope); loop_scope->break_block = end_block; loop_scope->continue_block = continue_block; loop_scope->is_comptime = is_comptime; @@ -6114,47 +6114,47 @@ static IrInstSrc *ir_gen_while_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no // Note the body block of the loop is not the place that lval and result_loc are used - // it's actually in break statements, handled similarly to return statements. // That is why we set those values in loop_scope above and not in this ir_gen_node call. - IrInstSrc *body_result = ir_gen_node(irb, node->data.while_expr.body, &loop_scope->base); - if (body_result == irb->codegen->invalid_inst_src) + IrInstSrc *body_result = ir_gen_node(ag, node->data.while_expr.body, &loop_scope->base); + if (body_result == ag->codegen->invalid_inst_src) return body_result; if (loop_scope->name != nullptr && loop_scope->name_used == false) { - add_node_error(irb->codegen, node, buf_sprintf("unused while label")); + add_node_error(ag->codegen, node, buf_sprintf("unused while label")); } if (!instr_is_unreachable(body_result)) { - ir_mark_gen(ir_build_check_statement_is_void(irb, child_scope, node->data.while_expr.body, body_result)); - ir_mark_gen(ir_build_br(irb, child_scope, node, continue_block, is_comptime)); + ir_mark_gen(ir_build_check_statement_is_void(ag, child_scope, node->data.while_expr.body, body_result)); + ir_mark_gen(ir_build_br(ag, child_scope, node, continue_block, is_comptime)); } if (continue_expr_node) { - ir_set_cursor_at_end_and_append_block(irb, continue_block); - IrInstSrc *expr_result = ir_gen_node(irb, continue_expr_node, child_scope); - if (expr_result == irb->codegen->invalid_inst_src) + ir_set_cursor_at_end_and_append_block(ag, continue_block); + IrInstSrc *expr_result = ir_gen_node(ag, continue_expr_node, child_scope); + if (expr_result == ag->codegen->invalid_inst_src) return expr_result; if (!instr_is_unreachable(expr_result)) { - ir_mark_gen(ir_build_check_statement_is_void(irb, child_scope, continue_expr_node, expr_result)); - ir_mark_gen(ir_build_br(irb, child_scope, node, cond_block, is_comptime)); + ir_mark_gen(ir_build_check_statement_is_void(ag, child_scope, continue_expr_node, expr_result)); + ir_mark_gen(ir_build_br(ag, child_scope, node, cond_block, is_comptime)); } } IrInstSrc *else_result = nullptr; if (else_node) { - ir_set_cursor_at_end_and_append_block(irb, else_block); + ir_set_cursor_at_end_and_append_block(ag, else_block); if (peer_parent->peers.length != 0) { peer_parent->peers.last()->next_bb = else_block; } ResultLocPeer *peer_result = create_peer_result(peer_parent); peer_parent->peers.append(peer_result); - else_result = ir_gen_node_extra(irb, else_node, scope, lval, &peer_result->base); - if (else_result == irb->codegen->invalid_inst_src) + else_result = ir_gen_node_extra(ag, else_node, scope, lval, &peer_result->base); + if (else_result == ag->codegen->invalid_inst_src) return else_result; if (!instr_is_unreachable(else_result)) - ir_mark_gen(ir_build_br(irb, scope, node, end_block, is_comptime)); + ir_mark_gen(ir_build_br(ag, scope, node, end_block, is_comptime)); } - IrBasicBlockSrc *after_else_block = irb->current_basic_block; - ir_set_cursor_at_end_and_append_block(irb, end_block); + IrBasicBlockSrc *after_else_block = ag->current_basic_block; + ir_set_cursor_at_end_and_append_block(ag, end_block); if (else_result) { incoming_blocks.append(after_else_block); incoming_values.append(else_result); @@ -6166,39 +6166,39 @@ static IrInstSrc *ir_gen_while_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no peer_parent->peers.last()->next_bb = end_block; } - IrInstSrc *phi = ir_build_phi(irb, scope, node, incoming_blocks.length, + IrInstSrc *phi = ir_build_phi(ag, scope, node, incoming_blocks.length, incoming_blocks.items, incoming_values.items, peer_parent); - return ir_expr_wrap(irb, scope, phi, result_loc); + return ir_expr_wrap(ag, scope, phi, result_loc); } else { - ir_set_cursor_at_end_and_append_block(irb, cond_block); - IrInstSrc *cond_val = ir_gen_node(irb, node->data.while_expr.condition, scope); - if (cond_val == irb->codegen->invalid_inst_src) + ir_set_cursor_at_end_and_append_block(ag, cond_block); + IrInstSrc *cond_val = ir_gen_node(ag, node->data.while_expr.condition, scope); + if (cond_val == ag->codegen->invalid_inst_src) return cond_val; - IrBasicBlockSrc *after_cond_block = irb->current_basic_block; - IrInstSrc *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, scope, node)); + IrBasicBlockSrc *after_cond_block = ag->current_basic_block; + IrInstSrc *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(ag, scope, node)); IrInstSrc *cond_br_inst; if (!instr_is_unreachable(cond_val)) { - cond_br_inst = ir_build_cond_br(irb, scope, node->data.while_expr.condition, cond_val, + cond_br_inst = ir_build_cond_br(ag, scope, node->data.while_expr.condition, cond_val, body_block, else_block, is_comptime); cond_br_inst->is_gen = true; } else { // for the purposes of the source instruction to ir_build_result_peers - cond_br_inst = irb->current_basic_block->instruction_list.last(); + cond_br_inst = ag->current_basic_block->instruction_list.last(); } - ResultLocPeerParent *peer_parent = ir_build_result_peers(irb, cond_br_inst, end_block, result_loc, + ResultLocPeerParent *peer_parent = ir_build_result_peers(ag, cond_br_inst, end_block, result_loc, is_comptime); - ir_set_cursor_at_end_and_append_block(irb, body_block); + ir_set_cursor_at_end_and_append_block(ag, body_block); ZigList incoming_values = {0}; ZigList incoming_blocks = {0}; - Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime); + Scope *subexpr_scope = create_runtime_scope(ag->codegen, node, scope, is_comptime); - if (is_duplicate_label(irb->codegen, subexpr_scope, node, node->data.while_expr.name)) - return irb->codegen->invalid_inst_src; + if (is_duplicate_label(ag->codegen, subexpr_scope, node, node->data.while_expr.name)) + return ag->codegen->invalid_inst_src; - ScopeLoop *loop_scope = create_loop_scope(irb->codegen, node, subexpr_scope); + ScopeLoop *loop_scope = create_loop_scope(ag->codegen, node, subexpr_scope); loop_scope->break_block = end_block; loop_scope->continue_block = continue_block; loop_scope->is_comptime = is_comptime; @@ -6210,33 +6210,33 @@ static IrInstSrc *ir_gen_while_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no // Note the body block of the loop is not the place that lval and result_loc are used - // it's actually in break statements, handled similarly to return statements. // That is why we set those values in loop_scope above and not in this ir_gen_node call. - IrInstSrc *body_result = ir_gen_node(irb, node->data.while_expr.body, &loop_scope->base); - if (body_result == irb->codegen->invalid_inst_src) + IrInstSrc *body_result = ir_gen_node(ag, node->data.while_expr.body, &loop_scope->base); + if (body_result == ag->codegen->invalid_inst_src) return body_result; if (loop_scope->name != nullptr && loop_scope->name_used == false) { - add_node_error(irb->codegen, node, buf_sprintf("unused while label")); + add_node_error(ag->codegen, node, buf_sprintf("unused while label")); } if (!instr_is_unreachable(body_result)) { - ir_mark_gen(ir_build_check_statement_is_void(irb, scope, node->data.while_expr.body, body_result)); - ir_mark_gen(ir_build_br(irb, scope, node, continue_block, is_comptime)); + ir_mark_gen(ir_build_check_statement_is_void(ag, scope, node->data.while_expr.body, body_result)); + ir_mark_gen(ir_build_br(ag, scope, node, continue_block, is_comptime)); } if (continue_expr_node) { - ir_set_cursor_at_end_and_append_block(irb, continue_block); - IrInstSrc *expr_result = ir_gen_node(irb, continue_expr_node, subexpr_scope); - if (expr_result == irb->codegen->invalid_inst_src) + ir_set_cursor_at_end_and_append_block(ag, continue_block); + IrInstSrc *expr_result = ir_gen_node(ag, continue_expr_node, subexpr_scope); + if (expr_result == ag->codegen->invalid_inst_src) return expr_result; if (!instr_is_unreachable(expr_result)) { - ir_mark_gen(ir_build_check_statement_is_void(irb, scope, continue_expr_node, expr_result)); - ir_mark_gen(ir_build_br(irb, scope, node, cond_block, is_comptime)); + ir_mark_gen(ir_build_check_statement_is_void(ag, scope, continue_expr_node, expr_result)); + ir_mark_gen(ir_build_br(ag, scope, node, cond_block, is_comptime)); } } IrInstSrc *else_result = nullptr; if (else_node) { - ir_set_cursor_at_end_and_append_block(irb, else_block); + ir_set_cursor_at_end_and_append_block(ag, else_block); if (peer_parent->peers.length != 0) { peer_parent->peers.last()->next_bb = else_block; @@ -6244,14 +6244,14 @@ static IrInstSrc *ir_gen_while_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no ResultLocPeer *peer_result = create_peer_result(peer_parent); peer_parent->peers.append(peer_result); - else_result = ir_gen_node_extra(irb, else_node, subexpr_scope, lval, &peer_result->base); - if (else_result == irb->codegen->invalid_inst_src) + else_result = ir_gen_node_extra(ag, else_node, subexpr_scope, lval, &peer_result->base); + if (else_result == ag->codegen->invalid_inst_src) return else_result; if (!instr_is_unreachable(else_result)) - ir_mark_gen(ir_build_br(irb, scope, node, end_block, is_comptime)); + ir_mark_gen(ir_build_br(ag, scope, node, end_block, is_comptime)); } - IrBasicBlockSrc *after_else_block = irb->current_basic_block; - ir_set_cursor_at_end_and_append_block(irb, end_block); + IrBasicBlockSrc *after_else_block = ag->current_basic_block; + ir_set_cursor_at_end_and_append_block(ag, end_block); if (else_result) { incoming_blocks.append(after_else_block); incoming_values.append(else_result); @@ -6263,13 +6263,13 @@ static IrInstSrc *ir_gen_while_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no peer_parent->peers.last()->next_bb = end_block; } - IrInstSrc *phi = ir_build_phi(irb, scope, node, incoming_blocks.length, + IrInstSrc *phi = ir_build_phi(ag, scope, node, incoming_blocks.length, incoming_blocks.items, incoming_values.items, peer_parent); - return ir_expr_wrap(irb, scope, phi, result_loc); + return ir_expr_wrap(ag, scope, phi, result_loc); } } -static IrInstSrc *ir_gen_for_expr(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node, LVal lval, +static IrInstSrc *ir_gen_for_expr(Stage1AstGen *ag, Scope *parent_scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypeForExpr); @@ -6281,19 +6281,19 @@ static IrInstSrc *ir_gen_for_expr(IrBuilderSrc *irb, Scope *parent_scope, AstNod AstNode *else_node = node->data.for_expr.else_node; if (!elem_node) { - add_node_error(irb->codegen, node, buf_sprintf("for loop expression missing element parameter")); - return irb->codegen->invalid_inst_src; + add_node_error(ag->codegen, node, buf_sprintf("for loop expression missing element parameter")); + return ag->codegen->invalid_inst_src; } assert(elem_node->type == NodeTypeIdentifier); - ScopeExpr *spill_scope = create_expr_scope(irb->codegen, node, parent_scope); + ScopeExpr *spill_scope = create_expr_scope(ag->codegen, node, parent_scope); - IrInstSrc *array_val_ptr = ir_gen_node_extra(irb, array_node, &spill_scope->base, LValPtr, nullptr); - if (array_val_ptr == irb->codegen->invalid_inst_src) + IrInstSrc *array_val_ptr = ir_gen_node_extra(ag, array_node, &spill_scope->base, LValPtr, nullptr); + if (array_val_ptr == ag->codegen->invalid_inst_src) return array_val_ptr; - IrInstSrc *is_comptime = ir_build_const_bool(irb, parent_scope, node, - ir_should_inline(irb->exec, parent_scope) || node->data.for_expr.is_inline); + IrInstSrc *is_comptime = ir_build_const_bool(ag, parent_scope, node, + ir_should_inline(ag->exec, parent_scope) || node->data.for_expr.is_inline); AstNode *index_var_source_node; ZigVar *index_var; @@ -6301,61 +6301,61 @@ static IrInstSrc *ir_gen_for_expr(IrBuilderSrc *irb, Scope *parent_scope, AstNod if (index_node) { index_var_source_node = index_node; Buf *index_var_name_buf = node_identifier_buf(index_node); - index_var = ir_create_var(irb, index_node, parent_scope, index_var_name_buf, true, false, false, is_comptime); + index_var = ir_create_var(ag, index_node, parent_scope, index_var_name_buf, true, false, false, is_comptime); index_var_name = buf_ptr(index_var_name_buf); } else { index_var_source_node = node; - index_var = ir_create_var(irb, node, parent_scope, nullptr, true, false, true, is_comptime); + index_var = ir_create_var(ag, node, parent_scope, nullptr, true, false, true, is_comptime); index_var_name = "i"; } - IrInstSrc *zero = ir_build_const_usize(irb, parent_scope, node, 0); - build_decl_var_and_init(irb, parent_scope, index_var_source_node, index_var, zero, index_var_name, is_comptime); + IrInstSrc *zero = ir_build_const_usize(ag, parent_scope, node, 0); + build_decl_var_and_init(ag, parent_scope, index_var_source_node, index_var, zero, index_var_name, is_comptime); parent_scope = index_var->child_scope; - IrInstSrc *one = ir_build_const_usize(irb, parent_scope, node, 1); - IrInstSrc *index_ptr = ir_build_var_ptr(irb, parent_scope, node, index_var); + IrInstSrc *one = ir_build_const_usize(ag, parent_scope, node, 1); + IrInstSrc *index_ptr = ir_build_var_ptr(ag, parent_scope, node, index_var); - IrBasicBlockSrc *cond_block = ir_create_basic_block(irb, parent_scope, "ForCond"); - IrBasicBlockSrc *body_block = ir_create_basic_block(irb, parent_scope, "ForBody"); - IrBasicBlockSrc *end_block = ir_create_basic_block(irb, parent_scope, "ForEnd"); - IrBasicBlockSrc *else_block = else_node ? ir_create_basic_block(irb, parent_scope, "ForElse") : end_block; - IrBasicBlockSrc *continue_block = ir_create_basic_block(irb, parent_scope, "ForContinue"); + IrBasicBlockSrc *cond_block = ir_create_basic_block(ag, parent_scope, "ForCond"); + IrBasicBlockSrc *body_block = ir_create_basic_block(ag, parent_scope, "ForBody"); + IrBasicBlockSrc *end_block = ir_create_basic_block(ag, parent_scope, "ForEnd"); + IrBasicBlockSrc *else_block = else_node ? ir_create_basic_block(ag, parent_scope, "ForElse") : end_block; + IrBasicBlockSrc *continue_block = ir_create_basic_block(ag, parent_scope, "ForContinue"); Buf *len_field_name = buf_create_from_str("len"); - IrInstSrc *len_ref = ir_build_field_ptr(irb, parent_scope, node, array_val_ptr, len_field_name, false); - IrInstSrc *len_val = ir_build_load_ptr(irb, &spill_scope->base, node, len_ref); - ir_build_br(irb, parent_scope, node, cond_block, is_comptime); + IrInstSrc *len_ref = ir_build_field_ptr(ag, parent_scope, node, array_val_ptr, len_field_name, false); + IrInstSrc *len_val = ir_build_load_ptr(ag, &spill_scope->base, node, len_ref); + ir_build_br(ag, parent_scope, node, cond_block, is_comptime); - ir_set_cursor_at_end_and_append_block(irb, cond_block); - IrInstSrc *index_val = ir_build_load_ptr(irb, &spill_scope->base, node, index_ptr); - IrInstSrc *cond = ir_build_bin_op(irb, parent_scope, node, IrBinOpCmpLessThan, index_val, len_val, false); - IrBasicBlockSrc *after_cond_block = irb->current_basic_block; - IrInstSrc *void_else_value = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, parent_scope, node)); - IrInstSrc *cond_br_inst = ir_mark_gen(ir_build_cond_br(irb, parent_scope, node, cond, + ir_set_cursor_at_end_and_append_block(ag, cond_block); + IrInstSrc *index_val = ir_build_load_ptr(ag, &spill_scope->base, node, index_ptr); + IrInstSrc *cond = ir_build_bin_op(ag, parent_scope, node, IrBinOpCmpLessThan, index_val, len_val, false); + IrBasicBlockSrc *after_cond_block = ag->current_basic_block; + IrInstSrc *void_else_value = else_node ? nullptr : ir_mark_gen(ir_build_const_void(ag, parent_scope, node)); + IrInstSrc *cond_br_inst = ir_mark_gen(ir_build_cond_br(ag, parent_scope, node, cond, body_block, else_block, is_comptime)); - ResultLocPeerParent *peer_parent = ir_build_result_peers(irb, cond_br_inst, end_block, result_loc, is_comptime); + ResultLocPeerParent *peer_parent = ir_build_result_peers(ag, cond_br_inst, end_block, result_loc, is_comptime); - ir_set_cursor_at_end_and_append_block(irb, body_block); - IrInstSrc *elem_ptr = ir_build_elem_ptr(irb, &spill_scope->base, node, array_val_ptr, index_val, + ir_set_cursor_at_end_and_append_block(ag, body_block); + IrInstSrc *elem_ptr = ir_build_elem_ptr(ag, &spill_scope->base, node, array_val_ptr, index_val, false, PtrLenSingle, nullptr); // TODO make it an error to write to element variable or i variable. Buf *elem_var_name = node_identifier_buf(elem_node); - ZigVar *elem_var = ir_create_var(irb, elem_node, parent_scope, elem_var_name, true, false, false, is_comptime); + ZigVar *elem_var = ir_create_var(ag, elem_node, parent_scope, elem_var_name, true, false, false, is_comptime); Scope *child_scope = elem_var->child_scope; IrInstSrc *elem_value = node->data.for_expr.elem_is_ptr ? - elem_ptr : ir_build_load_ptr(irb, &spill_scope->base, elem_node, elem_ptr); - build_decl_var_and_init(irb, parent_scope, elem_node, elem_var, elem_value, buf_ptr(elem_var_name), is_comptime); + elem_ptr : ir_build_load_ptr(ag, &spill_scope->base, elem_node, elem_ptr); + build_decl_var_and_init(ag, parent_scope, elem_node, elem_var, elem_value, buf_ptr(elem_var_name), is_comptime); - if (is_duplicate_label(irb->codegen, child_scope, node, node->data.for_expr.name)) - return irb->codegen->invalid_inst_src; + if (is_duplicate_label(ag->codegen, child_scope, node, node->data.for_expr.name)) + return ag->codegen->invalid_inst_src; ZigList incoming_values = {0}; ZigList incoming_blocks = {0}; - ScopeLoop *loop_scope = create_loop_scope(irb->codegen, node, child_scope); + ScopeLoop *loop_scope = create_loop_scope(ag->codegen, node, child_scope); loop_scope->break_block = end_block; loop_scope->continue_block = continue_block; loop_scope->is_comptime = is_comptime; @@ -6368,41 +6368,41 @@ static IrInstSrc *ir_gen_for_expr(IrBuilderSrc *irb, Scope *parent_scope, AstNod // Note the body block of the loop is not the place that lval and result_loc are used - // it's actually in break statements, handled similarly to return statements. // That is why we set those values in loop_scope above and not in this ir_gen_node call. - IrInstSrc *body_result = ir_gen_node(irb, body_node, &loop_scope->base); - if (body_result == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; + IrInstSrc *body_result = ir_gen_node(ag, body_node, &loop_scope->base); + if (body_result == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; if (loop_scope->name != nullptr && loop_scope->name_used == false) { - add_node_error(irb->codegen, node, buf_sprintf("unused for label")); + add_node_error(ag->codegen, node, buf_sprintf("unused for label")); } if (!instr_is_unreachable(body_result)) { - ir_mark_gen(ir_build_check_statement_is_void(irb, child_scope, node->data.for_expr.body, body_result)); - ir_mark_gen(ir_build_br(irb, child_scope, node, continue_block, is_comptime)); + ir_mark_gen(ir_build_check_statement_is_void(ag, child_scope, node->data.for_expr.body, body_result)); + ir_mark_gen(ir_build_br(ag, child_scope, node, continue_block, is_comptime)); } - ir_set_cursor_at_end_and_append_block(irb, continue_block); - IrInstSrc *new_index_val = ir_build_bin_op(irb, child_scope, node, IrBinOpAdd, index_val, one, false); - ir_build_store_ptr(irb, child_scope, node, index_ptr, new_index_val)->allow_write_through_const = true; - ir_build_br(irb, child_scope, node, cond_block, is_comptime); + ir_set_cursor_at_end_and_append_block(ag, continue_block); + IrInstSrc *new_index_val = ir_build_bin_op(ag, child_scope, node, IrBinOpAdd, index_val, one, false); + ir_build_store_ptr(ag, child_scope, node, index_ptr, new_index_val)->allow_write_through_const = true; + ir_build_br(ag, child_scope, node, cond_block, is_comptime); IrInstSrc *else_result = nullptr; if (else_node) { - ir_set_cursor_at_end_and_append_block(irb, else_block); + ir_set_cursor_at_end_and_append_block(ag, else_block); if (peer_parent->peers.length != 0) { peer_parent->peers.last()->next_bb = else_block; } ResultLocPeer *peer_result = create_peer_result(peer_parent); peer_parent->peers.append(peer_result); - else_result = ir_gen_node_extra(irb, else_node, parent_scope, LValNone, &peer_result->base); - if (else_result == irb->codegen->invalid_inst_src) + else_result = ir_gen_node_extra(ag, else_node, parent_scope, LValNone, &peer_result->base); + if (else_result == ag->codegen->invalid_inst_src) return else_result; if (!instr_is_unreachable(else_result)) - ir_mark_gen(ir_build_br(irb, parent_scope, node, end_block, is_comptime)); + ir_mark_gen(ir_build_br(ag, parent_scope, node, end_block, is_comptime)); } - IrBasicBlockSrc *after_else_block = irb->current_basic_block; - ir_set_cursor_at_end_and_append_block(irb, end_block); + IrBasicBlockSrc *after_else_block = ag->current_basic_block; + ir_set_cursor_at_end_and_append_block(ag, end_block); if (else_result) { incoming_blocks.append(after_else_block); @@ -6415,24 +6415,24 @@ static IrInstSrc *ir_gen_for_expr(IrBuilderSrc *irb, Scope *parent_scope, AstNod peer_parent->peers.last()->next_bb = end_block; } - IrInstSrc *phi = ir_build_phi(irb, parent_scope, node, incoming_blocks.length, + IrInstSrc *phi = ir_build_phi(ag, parent_scope, node, incoming_blocks.length, incoming_blocks.items, incoming_values.items, peer_parent); - return ir_lval_wrap(irb, parent_scope, phi, lval, result_loc); + return ir_lval_wrap(ag, parent_scope, phi, lval, result_loc); } -static IrInstSrc *ir_gen_bool_literal(IrBuilderSrc *irb, Scope *scope, AstNode *node) { +static IrInstSrc *ir_gen_bool_literal(Stage1AstGen *ag, Scope *scope, AstNode *node) { assert(node->type == NodeTypeBoolLiteral); - return ir_build_const_bool(irb, scope, node, node->data.bool_literal.value); + return ir_build_const_bool(ag, scope, node, node->data.bool_literal.value); } -static IrInstSrc *ir_gen_enum_literal(IrBuilderSrc *irb, Scope *scope, AstNode *node) { +static IrInstSrc *ir_gen_enum_literal(Stage1AstGen *ag, Scope *scope, AstNode *node) { assert(node->type == NodeTypeEnumLiteral); RootStruct *root_struct = node->owner->data.structure.root_struct; Buf *name = token_identifier_buf(root_struct, node->main_token + 1); - return ir_build_const_enum_literal(irb, scope, node, name); + return ir_build_const_enum_literal(ag, scope, node, name); } -static IrInstSrc *ir_gen_string_literal(IrBuilderSrc *irb, Scope *scope, AstNode *node) { +static IrInstSrc *ir_gen_string_literal(Stage1AstGen *ag, Scope *scope, AstNode *node) { Error err; assert(node->type == NodeTypeStringLiteral); @@ -6446,7 +6446,7 @@ static IrInstSrc *ir_gen_string_literal(IrBuilderSrc *irb, Scope *scope, AstNode size_t byte_offset = root_struct->token_locs[node->main_token].offset; size_t bad_index; if ((err = source_string_literal_buf(source + byte_offset, str, &bad_index))) { - add_token_error_offset(irb->codegen, node->owner, node->main_token, + add_token_error_offset(ag->codegen, node->owner, node->main_token, buf_create_from_str("invalid string literal character"), bad_index); } src_assert(source[byte_offset] == '"', node); @@ -6470,10 +6470,10 @@ static IrInstSrc *ir_gen_string_literal(IrBuilderSrc *irb, Scope *scope, AstNode } else { zig_unreachable(); } - return ir_build_const_str_lit(irb, scope, node, str); + return ir_build_const_str_lit(ag, scope, node, str); } -static IrInstSrc *ir_gen_array_type(IrBuilderSrc *irb, Scope *scope, AstNode *node) { +static IrInstSrc *ir_gen_array_type(Stage1AstGen *ag, Scope *scope, AstNode *node) { assert(node->type == NodeTypeArrayType); AstNode *size_node = node->data.array_type.size; @@ -6484,12 +6484,12 @@ static IrInstSrc *ir_gen_array_type(IrBuilderSrc *irb, Scope *scope, AstNode *no AstNode *sentinel_expr = node->data.array_type.sentinel; AstNode *align_expr = node->data.array_type.align_expr; - Scope *comptime_scope = create_comptime_scope(irb->codegen, node, scope); + Scope *comptime_scope = create_comptime_scope(ag->codegen, node, scope); IrInstSrc *sentinel; if (sentinel_expr != nullptr) { - sentinel = ir_gen_node(irb, sentinel_expr, comptime_scope); - if (sentinel == irb->codegen->invalid_inst_src) + sentinel = ir_gen_node(ag, sentinel_expr, comptime_scope); + if (sentinel == ag->codegen->invalid_inst_src) return sentinel; } else { sentinel = nullptr; @@ -6497,98 +6497,98 @@ static IrInstSrc *ir_gen_array_type(IrBuilderSrc *irb, Scope *scope, AstNode *no if (size_node) { if (is_const) { - add_node_error(irb->codegen, node, buf_create_from_str("const qualifier invalid on array type")); - return irb->codegen->invalid_inst_src; + add_node_error(ag->codegen, node, buf_create_from_str("const qualifier invalid on array type")); + return ag->codegen->invalid_inst_src; } if (is_volatile) { - add_node_error(irb->codegen, node, buf_create_from_str("volatile qualifier invalid on array type")); - return irb->codegen->invalid_inst_src; + add_node_error(ag->codegen, node, buf_create_from_str("volatile qualifier invalid on array type")); + return ag->codegen->invalid_inst_src; } if (is_allow_zero) { - add_node_error(irb->codegen, node, buf_create_from_str("allowzero qualifier invalid on array type")); - return irb->codegen->invalid_inst_src; + add_node_error(ag->codegen, node, buf_create_from_str("allowzero qualifier invalid on array type")); + return ag->codegen->invalid_inst_src; } if (align_expr != nullptr) { - add_node_error(irb->codegen, node, buf_create_from_str("align qualifier invalid on array type")); - return irb->codegen->invalid_inst_src; + add_node_error(ag->codegen, node, buf_create_from_str("align qualifier invalid on array type")); + return ag->codegen->invalid_inst_src; } - IrInstSrc *size_value = ir_gen_node(irb, size_node, comptime_scope); - if (size_value == irb->codegen->invalid_inst_src) + IrInstSrc *size_value = ir_gen_node(ag, size_node, comptime_scope); + if (size_value == ag->codegen->invalid_inst_src) return size_value; - IrInstSrc *child_type = ir_gen_node(irb, child_type_node, comptime_scope); - if (child_type == irb->codegen->invalid_inst_src) + IrInstSrc *child_type = ir_gen_node(ag, child_type_node, comptime_scope); + if (child_type == ag->codegen->invalid_inst_src) return child_type; - return ir_build_array_type(irb, scope, node, size_value, sentinel, child_type); + return ir_build_array_type(ag, scope, node, size_value, sentinel, child_type); } else { IrInstSrc *align_value; if (align_expr != nullptr) { - align_value = ir_gen_node(irb, align_expr, comptime_scope); - if (align_value == irb->codegen->invalid_inst_src) + align_value = ir_gen_node(ag, align_expr, comptime_scope); + if (align_value == ag->codegen->invalid_inst_src) return align_value; } else { align_value = nullptr; } - IrInstSrc *child_type = ir_gen_node(irb, child_type_node, comptime_scope); - if (child_type == irb->codegen->invalid_inst_src) + IrInstSrc *child_type = ir_gen_node(ag, child_type_node, comptime_scope); + if (child_type == ag->codegen->invalid_inst_src) return child_type; - return ir_build_slice_type(irb, scope, node, child_type, is_const, is_volatile, sentinel, + return ir_build_slice_type(ag, scope, node, child_type, is_const, is_volatile, sentinel, align_value, is_allow_zero); } } -static IrInstSrc *ir_gen_anyframe_type(IrBuilderSrc *irb, Scope *scope, AstNode *node) { +static IrInstSrc *ir_gen_anyframe_type(Stage1AstGen *ag, Scope *scope, AstNode *node) { assert(node->type == NodeTypeAnyFrameType); AstNode *payload_type_node = node->data.anyframe_type.payload_type; IrInstSrc *payload_type_value = nullptr; if (payload_type_node != nullptr) { - payload_type_value = ir_gen_node(irb, payload_type_node, scope); - if (payload_type_value == irb->codegen->invalid_inst_src) + payload_type_value = ir_gen_node(ag, payload_type_node, scope); + if (payload_type_value == ag->codegen->invalid_inst_src) return payload_type_value; } - return ir_build_anyframe_type(irb, scope, node, payload_type_value); + return ir_build_anyframe_type(ag, scope, node, payload_type_value); } -static IrInstSrc *ir_gen_undefined_literal(IrBuilderSrc *irb, Scope *scope, AstNode *node) { +static IrInstSrc *ir_gen_undefined_literal(Stage1AstGen *ag, Scope *scope, AstNode *node) { assert(node->type == NodeTypeUndefinedLiteral); - return ir_build_const_undefined(irb, scope, node); + return ir_build_const_undefined(ag, scope, node); } -static IrInstSrc *ir_gen_asm_expr(IrBuilderSrc *irb, Scope *scope, AstNode *node) { +static IrInstSrc *ir_gen_asm_expr(Stage1AstGen *ag, Scope *scope, AstNode *node) { assert(node->type == NodeTypeAsmExpr); AstNodeAsmExpr *asm_expr = &node->data.asm_expr; - IrInstSrc *asm_template = ir_gen_node(irb, asm_expr->asm_template, scope); - if (asm_template == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; + IrInstSrc *asm_template = ir_gen_node(ag, asm_expr->asm_template, scope); + if (asm_template == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; bool is_volatile = asm_expr->volatile_token != 0; bool in_fn_scope = (scope_fn_entry(scope) != nullptr); if (!in_fn_scope) { if (is_volatile) { - add_token_error(irb->codegen, node->owner, asm_expr->volatile_token, + add_token_error(ag->codegen, node->owner, asm_expr->volatile_token, buf_sprintf("volatile is meaningless on global assembly")); - return irb->codegen->invalid_inst_src; + return ag->codegen->invalid_inst_src; } if (asm_expr->output_list.length != 0 || asm_expr->input_list.length != 0 || asm_expr->clobber_list.length != 0) { - add_node_error(irb->codegen, node, + add_node_error(ag->codegen, node, buf_sprintf("global assembly cannot have inputs, outputs, or clobbers")); - return irb->codegen->invalid_inst_src; + return ag->codegen->invalid_inst_src; } - return ir_build_asm_src(irb, scope, node, asm_template, nullptr, nullptr, + return ir_build_asm_src(ag, scope, node, asm_template, nullptr, nullptr, nullptr, 0, is_volatile, true); } @@ -6597,61 +6597,61 @@ static IrInstSrc *ir_gen_asm_expr(IrBuilderSrc *irb, Scope *scope, AstNode *node ZigVar **output_vars = heap::c_allocator.allocate(asm_expr->output_list.length); size_t return_count = 0; if (!is_volatile && asm_expr->output_list.length == 0) { - add_node_error(irb->codegen, node, + add_node_error(ag->codegen, node, buf_sprintf("assembly expression with no output must be marked volatile")); - return irb->codegen->invalid_inst_src; + return ag->codegen->invalid_inst_src; } for (size_t i = 0; i < asm_expr->output_list.length; i += 1) { AsmOutput *asm_output = asm_expr->output_list.at(i); if (asm_output->return_type) { return_count += 1; - IrInstSrc *return_type = ir_gen_node(irb, asm_output->return_type, scope); - if (return_type == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; + IrInstSrc *return_type = ir_gen_node(ag, asm_output->return_type, scope); + if (return_type == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; if (return_count > 1) { - add_node_error(irb->codegen, node, + add_node_error(ag->codegen, node, buf_sprintf("inline assembly allows up to one output value")); - return irb->codegen->invalid_inst_src; + return ag->codegen->invalid_inst_src; } output_types[i] = return_type; } else { Buf *variable_name = asm_output->variable_name; // TODO there is some duplication here with ir_gen_symbol. I need to do a full audit of how // inline assembly works. https://github.com/ziglang/zig/issues/215 - ZigVar *var = find_variable(irb->codegen, scope, variable_name, nullptr); + ZigVar *var = find_variable(ag->codegen, scope, variable_name, nullptr); if (var) { output_vars[i] = var; } else { - add_node_error(irb->codegen, node, + add_node_error(ag->codegen, node, buf_sprintf("use of undeclared identifier '%s'", buf_ptr(variable_name))); - return irb->codegen->invalid_inst_src; + return ag->codegen->invalid_inst_src; } } const char modifier = *buf_ptr(asm_output->constraint); if (modifier != '=') { - add_node_error(irb->codegen, node, + add_node_error(ag->codegen, node, buf_sprintf("invalid modifier starting output constraint for '%s': '%c', only '=' is supported." " Compiler TODO: see https://github.com/ziglang/zig/issues/215", buf_ptr(asm_output->asm_symbolic_name), modifier)); - return irb->codegen->invalid_inst_src; + return ag->codegen->invalid_inst_src; } } for (size_t i = 0; i < asm_expr->input_list.length; i += 1) { AsmInput *asm_input = asm_expr->input_list.at(i); - IrInstSrc *input_value = ir_gen_node(irb, asm_input->expr, scope); - if (input_value == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; + IrInstSrc *input_value = ir_gen_node(ag, asm_input->expr, scope); + if (input_value == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; input_list[i] = input_value; } - return ir_build_asm_src(irb, scope, node, asm_template, input_list, output_types, + return ir_build_asm_src(ag, scope, node, asm_template, input_list, output_types, output_vars, return_count, is_volatile, false); } -static IrInstSrc *ir_gen_if_optional_expr(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, +static IrInstSrc *ir_gen_if_optional_expr(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypeIfOptional); @@ -6662,73 +6662,73 @@ static IrInstSrc *ir_gen_if_optional_expr(IrBuilderSrc *irb, Scope *scope, AstNo AstNode *else_node = node->data.test_expr.else_node; bool var_is_ptr = node->data.test_expr.var_is_ptr; - ScopeExpr *spill_scope = create_expr_scope(irb->codegen, expr_node, scope); + ScopeExpr *spill_scope = create_expr_scope(ag->codegen, expr_node, scope); spill_scope->spill_harder = true; - IrInstSrc *maybe_val_ptr = ir_gen_node_extra(irb, expr_node, &spill_scope->base, LValPtr, nullptr); - if (maybe_val_ptr == irb->codegen->invalid_inst_src) + IrInstSrc *maybe_val_ptr = ir_gen_node_extra(ag, expr_node, &spill_scope->base, LValPtr, nullptr); + if (maybe_val_ptr == ag->codegen->invalid_inst_src) return maybe_val_ptr; - IrInstSrc *maybe_val = ir_build_load_ptr(irb, scope, node, maybe_val_ptr); - IrInstSrc *is_non_null = ir_build_test_non_null_src(irb, scope, node, maybe_val); + IrInstSrc *maybe_val = ir_build_load_ptr(ag, scope, node, maybe_val_ptr); + IrInstSrc *is_non_null = ir_build_test_non_null_src(ag, scope, node, maybe_val); - IrBasicBlockSrc *then_block = ir_create_basic_block(irb, scope, "OptionalThen"); - IrBasicBlockSrc *else_block = ir_create_basic_block(irb, scope, "OptionalElse"); - IrBasicBlockSrc *endif_block = ir_create_basic_block(irb, scope, "OptionalEndIf"); + IrBasicBlockSrc *then_block = ir_create_basic_block(ag, scope, "OptionalThen"); + IrBasicBlockSrc *else_block = ir_create_basic_block(ag, scope, "OptionalElse"); + IrBasicBlockSrc *endif_block = ir_create_basic_block(ag, scope, "OptionalEndIf"); IrInstSrc *is_comptime; - if (ir_should_inline(irb->exec, scope)) { - is_comptime = ir_build_const_bool(irb, scope, node, true); + if (ir_should_inline(ag->exec, scope)) { + is_comptime = ir_build_const_bool(ag, scope, node, true); } else { - is_comptime = ir_build_test_comptime(irb, scope, node, is_non_null); + is_comptime = ir_build_test_comptime(ag, scope, node, is_non_null); } - IrInstSrc *cond_br_inst = ir_build_cond_br(irb, scope, node, is_non_null, + IrInstSrc *cond_br_inst = ir_build_cond_br(ag, scope, node, is_non_null, then_block, else_block, is_comptime); - ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, else_block, endif_block, + ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(ag, cond_br_inst, else_block, endif_block, result_loc, is_comptime); - ir_set_cursor_at_end_and_append_block(irb, then_block); + ir_set_cursor_at_end_and_append_block(ag, then_block); - Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, &spill_scope->base, is_comptime); + Scope *subexpr_scope = create_runtime_scope(ag->codegen, node, &spill_scope->base, is_comptime); Scope *var_scope; if (var_symbol) { bool is_shadowable = false; bool is_const = true; - ZigVar *var = ir_create_var(irb, node, subexpr_scope, + ZigVar *var = ir_create_var(ag, node, subexpr_scope, var_symbol, is_const, is_const, is_shadowable, is_comptime); - IrInstSrc *payload_ptr = ir_build_optional_unwrap_ptr(irb, subexpr_scope, node, maybe_val_ptr, false); + IrInstSrc *payload_ptr = ir_build_optional_unwrap_ptr(ag, subexpr_scope, node, maybe_val_ptr, false); IrInstSrc *var_value = var_is_ptr ? - payload_ptr : ir_build_load_ptr(irb, &spill_scope->base, node, payload_ptr); - build_decl_var_and_init(irb, subexpr_scope, node, var, var_value, buf_ptr(var_symbol), is_comptime); + payload_ptr : ir_build_load_ptr(ag, &spill_scope->base, node, payload_ptr); + build_decl_var_and_init(ag, subexpr_scope, node, var, var_value, buf_ptr(var_symbol), is_comptime); var_scope = var->child_scope; } else { var_scope = subexpr_scope; } - IrInstSrc *then_expr_result = ir_gen_node_extra(irb, then_node, var_scope, lval, + IrInstSrc *then_expr_result = ir_gen_node_extra(ag, then_node, var_scope, lval, &peer_parent->peers.at(0)->base); - if (then_expr_result == irb->codegen->invalid_inst_src) + if (then_expr_result == ag->codegen->invalid_inst_src) return then_expr_result; - IrBasicBlockSrc *after_then_block = irb->current_basic_block; + IrBasicBlockSrc *after_then_block = ag->current_basic_block; if (!instr_is_unreachable(then_expr_result)) - ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime)); + ir_mark_gen(ir_build_br(ag, scope, node, endif_block, is_comptime)); - ir_set_cursor_at_end_and_append_block(irb, else_block); + ir_set_cursor_at_end_and_append_block(ag, else_block); IrInstSrc *else_expr_result; if (else_node) { - else_expr_result = ir_gen_node_extra(irb, else_node, subexpr_scope, lval, &peer_parent->peers.at(1)->base); - if (else_expr_result == irb->codegen->invalid_inst_src) + else_expr_result = ir_gen_node_extra(ag, else_node, subexpr_scope, lval, &peer_parent->peers.at(1)->base); + if (else_expr_result == ag->codegen->invalid_inst_src) return else_expr_result; } else { - else_expr_result = ir_build_const_void(irb, scope, node); - ir_build_end_expr(irb, scope, node, else_expr_result, &peer_parent->peers.at(1)->base); + else_expr_result = ir_build_const_void(ag, scope, node); + ir_build_end_expr(ag, scope, node, else_expr_result, &peer_parent->peers.at(1)->base); } - IrBasicBlockSrc *after_else_block = irb->current_basic_block; + IrBasicBlockSrc *after_else_block = ag->current_basic_block; if (!instr_is_unreachable(else_expr_result)) - ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime)); + ir_mark_gen(ir_build_br(ag, scope, node, endif_block, is_comptime)); - ir_set_cursor_at_end_and_append_block(irb, endif_block); + ir_set_cursor_at_end_and_append_block(ag, endif_block); IrInstSrc **incoming_values = heap::c_allocator.allocate(2); incoming_values[0] = then_expr_result; incoming_values[1] = else_expr_result; @@ -6736,11 +6736,11 @@ static IrInstSrc *ir_gen_if_optional_expr(IrBuilderSrc *irb, Scope *scope, AstNo incoming_blocks[0] = after_then_block; incoming_blocks[1] = after_else_block; - IrInstSrc *phi = ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, peer_parent); - return ir_expr_wrap(irb, scope, phi, result_loc); + IrInstSrc *phi = ir_build_phi(ag, scope, node, 2, incoming_blocks, incoming_values, peer_parent); + return ir_expr_wrap(ag, scope, phi, result_loc); } -static IrInstSrc *ir_gen_if_err_expr(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, +static IrInstSrc *ir_gen_if_err_expr(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypeIfErrorExpr); @@ -6753,51 +6753,51 @@ static IrInstSrc *ir_gen_if_err_expr(IrBuilderSrc *irb, Scope *scope, AstNode *n Buf *var_symbol = node->data.if_err_expr.var_symbol; Buf *err_symbol = node->data.if_err_expr.err_symbol; - IrInstSrc *err_val_ptr = ir_gen_node_extra(irb, target_node, scope, LValPtr, nullptr); - if (err_val_ptr == irb->codegen->invalid_inst_src) + IrInstSrc *err_val_ptr = ir_gen_node_extra(ag, target_node, scope, LValPtr, nullptr); + if (err_val_ptr == ag->codegen->invalid_inst_src) return err_val_ptr; - IrInstSrc *err_val = ir_build_load_ptr(irb, scope, node, err_val_ptr); - IrInstSrc *is_err = ir_build_test_err_src(irb, scope, node, err_val_ptr, true, false); + IrInstSrc *err_val = ir_build_load_ptr(ag, scope, node, err_val_ptr); + IrInstSrc *is_err = ir_build_test_err_src(ag, scope, node, err_val_ptr, true, false); - IrBasicBlockSrc *ok_block = ir_create_basic_block(irb, scope, "TryOk"); - IrBasicBlockSrc *else_block = ir_create_basic_block(irb, scope, "TryElse"); - IrBasicBlockSrc *endif_block = ir_create_basic_block(irb, scope, "TryEnd"); + IrBasicBlockSrc *ok_block = ir_create_basic_block(ag, scope, "TryOk"); + IrBasicBlockSrc *else_block = ir_create_basic_block(ag, scope, "TryElse"); + IrBasicBlockSrc *endif_block = ir_create_basic_block(ag, scope, "TryEnd"); - bool force_comptime = ir_should_inline(irb->exec, scope); - IrInstSrc *is_comptime = force_comptime ? ir_build_const_bool(irb, scope, node, true) : ir_build_test_comptime(irb, scope, node, is_err); - IrInstSrc *cond_br_inst = ir_build_cond_br(irb, scope, node, is_err, else_block, ok_block, is_comptime); + bool force_comptime = ir_should_inline(ag->exec, scope); + IrInstSrc *is_comptime = force_comptime ? ir_build_const_bool(ag, scope, node, true) : ir_build_test_comptime(ag, scope, node, is_err); + IrInstSrc *cond_br_inst = ir_build_cond_br(ag, scope, node, is_err, else_block, ok_block, is_comptime); - ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, else_block, endif_block, + ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(ag, cond_br_inst, else_block, endif_block, result_loc, is_comptime); - ir_set_cursor_at_end_and_append_block(irb, ok_block); + ir_set_cursor_at_end_and_append_block(ag, ok_block); - Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime); + Scope *subexpr_scope = create_runtime_scope(ag->codegen, node, scope, is_comptime); Scope *var_scope; if (var_symbol) { bool is_shadowable = false; - IrInstSrc *var_is_comptime = force_comptime ? ir_build_const_bool(irb, subexpr_scope, node, true) : ir_build_test_comptime(irb, subexpr_scope, node, err_val); - ZigVar *var = ir_create_var(irb, node, subexpr_scope, + IrInstSrc *var_is_comptime = force_comptime ? ir_build_const_bool(ag, subexpr_scope, node, true) : ir_build_test_comptime(ag, subexpr_scope, node, err_val); + ZigVar *var = ir_create_var(ag, node, subexpr_scope, var_symbol, var_is_const, var_is_const, is_shadowable, var_is_comptime); - IrInstSrc *payload_ptr = ir_build_unwrap_err_payload_src(irb, subexpr_scope, node, err_val_ptr, false, false); + IrInstSrc *payload_ptr = ir_build_unwrap_err_payload_src(ag, subexpr_scope, node, err_val_ptr, false, false); IrInstSrc *var_value = var_is_ptr ? - payload_ptr : ir_build_load_ptr(irb, subexpr_scope, node, payload_ptr); - build_decl_var_and_init(irb, subexpr_scope, node, var, var_value, buf_ptr(var_symbol), var_is_comptime); + payload_ptr : ir_build_load_ptr(ag, subexpr_scope, node, payload_ptr); + build_decl_var_and_init(ag, subexpr_scope, node, var, var_value, buf_ptr(var_symbol), var_is_comptime); var_scope = var->child_scope; } else { var_scope = subexpr_scope; } - IrInstSrc *then_expr_result = ir_gen_node_extra(irb, then_node, var_scope, lval, + IrInstSrc *then_expr_result = ir_gen_node_extra(ag, then_node, var_scope, lval, &peer_parent->peers.at(0)->base); - if (then_expr_result == irb->codegen->invalid_inst_src) + if (then_expr_result == ag->codegen->invalid_inst_src) return then_expr_result; - IrBasicBlockSrc *after_then_block = irb->current_basic_block; + IrBasicBlockSrc *after_then_block = ag->current_basic_block; if (!instr_is_unreachable(then_expr_result)) - ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime)); + ir_mark_gen(ir_build_br(ag, scope, node, endif_block, is_comptime)); - ir_set_cursor_at_end_and_append_block(irb, else_block); + ir_set_cursor_at_end_and_append_block(ag, else_block); IrInstSrc *else_expr_result; if (else_node) { @@ -6805,28 +6805,28 @@ static IrInstSrc *ir_gen_if_err_expr(IrBuilderSrc *irb, Scope *scope, AstNode *n if (err_symbol) { bool is_shadowable = false; bool is_const = true; - ZigVar *var = ir_create_var(irb, node, subexpr_scope, + ZigVar *var = ir_create_var(ag, node, subexpr_scope, err_symbol, is_const, is_const, is_shadowable, is_comptime); - IrInstSrc *err_ptr = ir_build_unwrap_err_code_src(irb, subexpr_scope, node, err_val_ptr); - IrInstSrc *err_value = ir_build_load_ptr(irb, subexpr_scope, node, err_ptr); - build_decl_var_and_init(irb, subexpr_scope, node, var, err_value, buf_ptr(err_symbol), is_comptime); + IrInstSrc *err_ptr = ir_build_unwrap_err_code_src(ag, subexpr_scope, node, err_val_ptr); + IrInstSrc *err_value = ir_build_load_ptr(ag, subexpr_scope, node, err_ptr); + build_decl_var_and_init(ag, subexpr_scope, node, var, err_value, buf_ptr(err_symbol), is_comptime); err_var_scope = var->child_scope; } else { err_var_scope = subexpr_scope; } - else_expr_result = ir_gen_node_extra(irb, else_node, err_var_scope, lval, &peer_parent->peers.at(1)->base); - if (else_expr_result == irb->codegen->invalid_inst_src) + else_expr_result = ir_gen_node_extra(ag, else_node, err_var_scope, lval, &peer_parent->peers.at(1)->base); + if (else_expr_result == ag->codegen->invalid_inst_src) return else_expr_result; } else { - else_expr_result = ir_build_const_void(irb, scope, node); - ir_build_end_expr(irb, scope, node, else_expr_result, &peer_parent->peers.at(1)->base); + else_expr_result = ir_build_const_void(ag, scope, node); + ir_build_end_expr(ag, scope, node, else_expr_result, &peer_parent->peers.at(1)->base); } - IrBasicBlockSrc *after_else_block = irb->current_basic_block; + IrBasicBlockSrc *after_else_block = ag->current_basic_block; if (!instr_is_unreachable(else_expr_result)) - ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime)); + ir_mark_gen(ir_build_br(ag, scope, node, endif_block, is_comptime)); - ir_set_cursor_at_end_and_append_block(irb, endif_block); + ir_set_cursor_at_end_and_append_block(ag, endif_block); IrInstSrc **incoming_values = heap::c_allocator.allocate(2); incoming_values[0] = then_expr_result; incoming_values[1] = else_expr_result; @@ -6834,11 +6834,11 @@ static IrInstSrc *ir_gen_if_err_expr(IrBuilderSrc *irb, Scope *scope, AstNode *n incoming_blocks[0] = after_then_block; incoming_blocks[1] = after_else_block; - IrInstSrc *phi = ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, peer_parent); - return ir_expr_wrap(irb, scope, phi, result_loc); + IrInstSrc *phi = ir_build_phi(ag, scope, node, 2, incoming_blocks, incoming_values, peer_parent); + return ir_expr_wrap(ag, scope, phi, result_loc); } -static bool ir_gen_switch_prong_expr(IrBuilderSrc *irb, Scope *scope, AstNode *switch_node, AstNode *prong_node, +static bool ir_gen_switch_prong_expr(Stage1AstGen *ag, Scope *scope, AstNode *switch_node, AstNode *prong_node, IrBasicBlockSrc *end_block, IrInstSrc *is_comptime, IrInstSrc *var_is_comptime, IrInstSrc *target_value_ptr, IrInstSrc **prong_values, size_t prong_values_len, ZigList *incoming_blocks, ZigList *incoming_values, @@ -6857,66 +6857,66 @@ static bool ir_gen_switch_prong_expr(IrBuilderSrc *irb, Scope *scope, AstNode *s bool is_shadowable = false; bool is_const = true; - ZigVar *var = ir_create_var(irb, var_symbol_node, scope, + ZigVar *var = ir_create_var(ag, var_symbol_node, scope, var_name, is_const, is_const, is_shadowable, var_is_comptime); child_scope = var->child_scope; IrInstSrc *var_value; if (out_switch_else_var != nullptr) { - IrInstSrcSwitchElseVar *switch_else_var = ir_build_switch_else_var(irb, scope, var_symbol_node, + IrInstSrcSwitchElseVar *switch_else_var = ir_build_switch_else_var(ag, scope, var_symbol_node, target_value_ptr); *out_switch_else_var = switch_else_var; IrInstSrc *payload_ptr = &switch_else_var->base; var_value = var_is_ptr ? - payload_ptr : ir_build_load_ptr(irb, scope, var_symbol_node, payload_ptr); + payload_ptr : ir_build_load_ptr(ag, scope, var_symbol_node, payload_ptr); } else if (prong_values != nullptr) { - IrInstSrc *payload_ptr = ir_build_switch_var(irb, scope, var_symbol_node, target_value_ptr, + IrInstSrc *payload_ptr = ir_build_switch_var(ag, scope, var_symbol_node, target_value_ptr, prong_values, prong_values_len); var_value = var_is_ptr ? - payload_ptr : ir_build_load_ptr(irb, scope, var_symbol_node, payload_ptr); + payload_ptr : ir_build_load_ptr(ag, scope, var_symbol_node, payload_ptr); } else { var_value = var_is_ptr ? - target_value_ptr : ir_build_load_ptr(irb, scope, var_symbol_node, target_value_ptr); + target_value_ptr : ir_build_load_ptr(ag, scope, var_symbol_node, target_value_ptr); } - build_decl_var_and_init(irb, scope, var_symbol_node, var, var_value, buf_ptr(var_name), var_is_comptime); + build_decl_var_and_init(ag, scope, var_symbol_node, var, var_value, buf_ptr(var_name), var_is_comptime); } else { child_scope = scope; } - IrInstSrc *expr_result = ir_gen_node_extra(irb, expr_node, child_scope, lval, result_loc); - if (expr_result == irb->codegen->invalid_inst_src) + IrInstSrc *expr_result = ir_gen_node_extra(ag, expr_node, child_scope, lval, result_loc); + if (expr_result == ag->codegen->invalid_inst_src) return false; if (!instr_is_unreachable(expr_result)) - ir_mark_gen(ir_build_br(irb, scope, switch_node, end_block, is_comptime)); - incoming_blocks->append(irb->current_basic_block); + ir_mark_gen(ir_build_br(ag, scope, switch_node, end_block, is_comptime)); + incoming_blocks->append(ag->current_basic_block); incoming_values->append(expr_result); return true; } -static IrInstSrc *ir_gen_switch_expr(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, +static IrInstSrc *ir_gen_switch_expr(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypeSwitchExpr); AstNode *target_node = node->data.switch_expr.expr; - IrInstSrc *target_value_ptr = ir_gen_node_extra(irb, target_node, scope, LValPtr, nullptr); - if (target_value_ptr == irb->codegen->invalid_inst_src) + IrInstSrc *target_value_ptr = ir_gen_node_extra(ag, target_node, scope, LValPtr, nullptr); + if (target_value_ptr == ag->codegen->invalid_inst_src) return target_value_ptr; - IrInstSrc *target_value = ir_build_switch_target(irb, scope, node, target_value_ptr); + IrInstSrc *target_value = ir_build_switch_target(ag, scope, node, target_value_ptr); - IrBasicBlockSrc *else_block = ir_create_basic_block(irb, scope, "SwitchElse"); - IrBasicBlockSrc *end_block = ir_create_basic_block(irb, scope, "SwitchEnd"); + IrBasicBlockSrc *else_block = ir_create_basic_block(ag, scope, "SwitchElse"); + IrBasicBlockSrc *end_block = ir_create_basic_block(ag, scope, "SwitchEnd"); size_t prong_count = node->data.switch_expr.prongs.length; ZigList cases = {0}; IrInstSrc *is_comptime; IrInstSrc *var_is_comptime; - if (ir_should_inline(irb->exec, scope)) { - is_comptime = ir_build_const_bool(irb, scope, node, true); + if (ir_should_inline(ag->exec, scope)) { + is_comptime = ir_build_const_bool(ag, scope, node, true); var_is_comptime = is_comptime; } else { - is_comptime = ir_build_test_comptime(irb, scope, node, target_value); - var_is_comptime = ir_build_test_comptime(irb, scope, node, target_value_ptr); + is_comptime = ir_build_test_comptime(ag, scope, node, target_value); + var_is_comptime = ir_build_test_comptime(ag, scope, node, target_value_ptr); } ZigList incoming_values = {0}; @@ -6932,11 +6932,11 @@ static IrInstSrc *ir_gen_switch_expr(IrBuilderSrc *irb, Scope *scope, AstNode *n peer_parent->is_comptime = is_comptime; peer_parent->parent = result_loc; - ir_build_reset_result(irb, scope, node, &peer_parent->base); + ir_build_reset_result(ag, scope, node, &peer_parent->base); // First do the else and the ranges - Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime); - Scope *comptime_scope = create_comptime_scope(irb->codegen, node, scope); + Scope *subexpr_scope = create_runtime_scope(ag->codegen, node, scope, is_comptime); + Scope *comptime_scope = create_comptime_scope(ag->codegen, node, scope); AstNode *else_prong = nullptr; AstNode *underscore_prong = nullptr; for (size_t prong_i = 0; prong_i < prong_count; prong_i += 1) { @@ -6954,54 +6954,54 @@ static IrInstSrc *ir_gen_switch_expr(IrBuilderSrc *irb, Scope *scope, AstNode *n AstNode *start_node = item_node->data.switch_range.start; AstNode *end_node = item_node->data.switch_range.end; - IrInstSrc *start_value = ir_gen_node(irb, start_node, comptime_scope); - if (start_value == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; + IrInstSrc *start_value = ir_gen_node(ag, start_node, comptime_scope); + if (start_value == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; - IrInstSrc *end_value = ir_gen_node(irb, end_node, comptime_scope); - if (end_value == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; + IrInstSrc *end_value = ir_gen_node(ag, end_node, comptime_scope); + if (end_value == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; IrInstSrcCheckSwitchProngsRange *check_range = check_ranges.add_one(); check_range->start = start_value; check_range->end = end_value; - IrInstSrc *lower_range_ok = ir_build_bin_op(irb, scope, item_node, IrBinOpCmpGreaterOrEq, + IrInstSrc *lower_range_ok = ir_build_bin_op(ag, scope, item_node, IrBinOpCmpGreaterOrEq, target_value, start_value, false); - IrInstSrc *upper_range_ok = ir_build_bin_op(irb, scope, item_node, IrBinOpCmpLessOrEq, + IrInstSrc *upper_range_ok = ir_build_bin_op(ag, scope, item_node, IrBinOpCmpLessOrEq, target_value, end_value, false); - IrInstSrc *both_ok = ir_build_bin_op(irb, scope, item_node, IrBinOpBoolAnd, + IrInstSrc *both_ok = ir_build_bin_op(ag, scope, item_node, IrBinOpBoolAnd, lower_range_ok, upper_range_ok, false); if (ok_bit) { - ok_bit = ir_build_bin_op(irb, scope, item_node, IrBinOpBoolOr, both_ok, ok_bit, false); + ok_bit = ir_build_bin_op(ag, scope, item_node, IrBinOpBoolOr, both_ok, ok_bit, false); } else { ok_bit = both_ok; } } else { - IrInstSrc *item_value = ir_gen_node(irb, item_node, comptime_scope); - if (item_value == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; + IrInstSrc *item_value = ir_gen_node(ag, item_node, comptime_scope); + if (item_value == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; IrInstSrcCheckSwitchProngsRange *check_range = check_ranges.add_one(); check_range->start = item_value; check_range->end = item_value; - IrInstSrc *cmp_ok = ir_build_bin_op(irb, scope, item_node, IrBinOpCmpEq, + IrInstSrc *cmp_ok = ir_build_bin_op(ag, scope, item_node, IrBinOpCmpEq, item_value, target_value, false); if (ok_bit) { - ok_bit = ir_build_bin_op(irb, scope, item_node, IrBinOpBoolOr, cmp_ok, ok_bit, false); + ok_bit = ir_build_bin_op(ag, scope, item_node, IrBinOpBoolOr, cmp_ok, ok_bit, false); } else { ok_bit = cmp_ok; } } } - IrBasicBlockSrc *range_block_yes = ir_create_basic_block(irb, scope, "SwitchRangeYes"); - IrBasicBlockSrc *range_block_no = ir_create_basic_block(irb, scope, "SwitchRangeNo"); + IrBasicBlockSrc *range_block_yes = ir_create_basic_block(ag, scope, "SwitchRangeYes"); + IrBasicBlockSrc *range_block_no = ir_create_basic_block(ag, scope, "SwitchRangeNo"); assert(ok_bit); assert(last_item_node); - IrInstSrc *br_inst = ir_mark_gen(ir_build_cond_br(irb, scope, last_item_node, ok_bit, + IrInstSrc *br_inst = ir_mark_gen(ir_build_cond_br(ag, scope, last_item_node, ok_bit, range_block_yes, range_block_no, is_comptime)); if (peer_parent->base.source_instruction == nullptr) { peer_parent->base.source_instruction = br_inst; @@ -7011,65 +7011,65 @@ static IrInstSrc *ir_gen_switch_expr(IrBuilderSrc *irb, Scope *scope, AstNode *n peer_parent->peers.last()->next_bb = range_block_yes; } peer_parent->peers.append(this_peer_result_loc); - ir_set_cursor_at_end_and_append_block(irb, range_block_yes); - if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block, + ir_set_cursor_at_end_and_append_block(ag, range_block_yes); + if (!ir_gen_switch_prong_expr(ag, subexpr_scope, node, prong_node, end_block, is_comptime, var_is_comptime, target_value_ptr, nullptr, 0, &incoming_blocks, &incoming_values, nullptr, LValNone, &this_peer_result_loc->base)) { - return irb->codegen->invalid_inst_src; + return ag->codegen->invalid_inst_src; } - ir_set_cursor_at_end_and_append_block(irb, range_block_no); + ir_set_cursor_at_end_and_append_block(ag, range_block_no); } else { if (prong_item_count == 0) { if (else_prong) { - ErrorMsg *msg = add_node_error(irb->codegen, prong_node, + ErrorMsg *msg = add_node_error(ag->codegen, prong_node, buf_sprintf("multiple else prongs in switch expression")); - add_error_note(irb->codegen, msg, else_prong, + add_error_note(ag->codegen, msg, else_prong, buf_sprintf("previous else prong is here")); - return irb->codegen->invalid_inst_src; + return ag->codegen->invalid_inst_src; } else_prong = prong_node; } else if (prong_item_count == 1 && prong_node->data.switch_prong.items.at(0)->type == NodeTypeIdentifier && buf_eql_str(node_identifier_buf(prong_node->data.switch_prong.items.at(0)), "_")) { if (underscore_prong) { - ErrorMsg *msg = add_node_error(irb->codegen, prong_node, + ErrorMsg *msg = add_node_error(ag->codegen, prong_node, buf_sprintf("multiple '_' prongs in switch expression")); - add_error_note(irb->codegen, msg, underscore_prong, + add_error_note(ag->codegen, msg, underscore_prong, buf_sprintf("previous '_' prong is here")); - return irb->codegen->invalid_inst_src; + return ag->codegen->invalid_inst_src; } underscore_prong = prong_node; } else { continue; } if (underscore_prong && else_prong) { - ErrorMsg *msg = add_node_error(irb->codegen, prong_node, + ErrorMsg *msg = add_node_error(ag->codegen, prong_node, buf_sprintf("else and '_' prong in switch expression")); if (underscore_prong == prong_node) - add_error_note(irb->codegen, msg, else_prong, + add_error_note(ag->codegen, msg, else_prong, buf_sprintf("else prong is here")); else - add_error_note(irb->codegen, msg, underscore_prong, + add_error_note(ag->codegen, msg, underscore_prong, buf_sprintf("'_' prong is here")); - return irb->codegen->invalid_inst_src; + return ag->codegen->invalid_inst_src; } ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent); - IrBasicBlockSrc *prev_block = irb->current_basic_block; + IrBasicBlockSrc *prev_block = ag->current_basic_block; if (peer_parent->peers.length > 0) { peer_parent->peers.last()->next_bb = else_block; } peer_parent->peers.append(this_peer_result_loc); - ir_set_cursor_at_end_and_append_block(irb, else_block); - if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block, + ir_set_cursor_at_end_and_append_block(ag, else_block); + if (!ir_gen_switch_prong_expr(ag, subexpr_scope, node, prong_node, end_block, is_comptime, var_is_comptime, target_value_ptr, nullptr, 0, &incoming_blocks, &incoming_values, &switch_else_var, LValNone, &this_peer_result_loc->base)) { - return irb->codegen->invalid_inst_src; + return ag->codegen->invalid_inst_src; } - ir_set_cursor_at_end(irb, prev_block); + ir_set_cursor_at_end(ag, prev_block); } } @@ -7086,16 +7086,16 @@ static IrInstSrc *ir_gen_switch_expr(IrBuilderSrc *irb, Scope *scope, AstNode *n ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent); - IrBasicBlockSrc *prong_block = ir_create_basic_block(irb, scope, "SwitchProng"); + IrBasicBlockSrc *prong_block = ir_create_basic_block(ag, scope, "SwitchProng"); IrInstSrc **items = heap::c_allocator.allocate(prong_item_count); for (size_t item_i = 0; item_i < prong_item_count; item_i += 1) { AstNode *item_node = prong_node->data.switch_prong.items.at(item_i); assert(item_node->type != NodeTypeSwitchRange); - IrInstSrc *item_value = ir_gen_node(irb, item_node, comptime_scope); - if (item_value == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; + IrInstSrc *item_value = ir_gen_node(ag, item_node, comptime_scope); + if (item_value == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; IrInstSrcCheckSwitchProngsRange *check_range = check_ranges.add_one(); check_range->start = item_value; @@ -7108,31 +7108,31 @@ static IrInstSrc *ir_gen_switch_expr(IrBuilderSrc *irb, Scope *scope, AstNode *n items[item_i] = item_value; } - IrBasicBlockSrc *prev_block = irb->current_basic_block; + IrBasicBlockSrc *prev_block = ag->current_basic_block; if (peer_parent->peers.length > 0) { peer_parent->peers.last()->next_bb = prong_block; } peer_parent->peers.append(this_peer_result_loc); - ir_set_cursor_at_end_and_append_block(irb, prong_block); - if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block, + ir_set_cursor_at_end_and_append_block(ag, prong_block); + if (!ir_gen_switch_prong_expr(ag, subexpr_scope, node, prong_node, end_block, is_comptime, var_is_comptime, target_value_ptr, items, prong_item_count, &incoming_blocks, &incoming_values, nullptr, LValNone, &this_peer_result_loc->base)) { - return irb->codegen->invalid_inst_src; + return ag->codegen->invalid_inst_src; } - ir_set_cursor_at_end(irb, prev_block); + ir_set_cursor_at_end(ag, prev_block); } - IrInstSrc *switch_prongs_void = ir_build_check_switch_prongs(irb, scope, node, target_value, + IrInstSrc *switch_prongs_void = ir_build_check_switch_prongs(ag, scope, node, target_value, check_ranges.items, check_ranges.length, else_prong, underscore_prong != nullptr); IrInstSrc *br_instruction; if (cases.length == 0) { - br_instruction = ir_build_br(irb, scope, node, else_block, is_comptime); + br_instruction = ir_build_br(ag, scope, node, else_block, is_comptime); } else { - IrInstSrcSwitchBr *switch_br = ir_build_switch_br_src(irb, scope, node, target_value, else_block, + IrInstSrcSwitchBr *switch_br = ir_build_switch_br_src(ag, scope, node, target_value, else_block, cases.length, cases.items, is_comptime, switch_prongs_void); if (switch_else_var != nullptr) { switch_else_var->switch_br = switch_br; @@ -7150,46 +7150,46 @@ static IrInstSrc *ir_gen_switch_expr(IrBuilderSrc *irb, Scope *scope, AstNode *n if (peer_parent->peers.length != 0) { peer_parent->peers.last()->next_bb = else_block; } - ir_set_cursor_at_end_and_append_block(irb, else_block); - ir_build_unreachable(irb, scope, node); + ir_set_cursor_at_end_and_append_block(ag, else_block); + ir_build_unreachable(ag, scope, node); } else { if (peer_parent->peers.length != 0) { peer_parent->peers.last()->next_bb = end_block; } } - ir_set_cursor_at_end_and_append_block(irb, end_block); + ir_set_cursor_at_end_and_append_block(ag, end_block); assert(incoming_blocks.length == incoming_values.length); IrInstSrc *result_instruction; if (incoming_blocks.length == 0) { - result_instruction = ir_build_const_void(irb, scope, node); + result_instruction = ir_build_const_void(ag, scope, node); } else { - result_instruction = ir_build_phi(irb, scope, node, incoming_blocks.length, + result_instruction = ir_build_phi(ag, scope, node, incoming_blocks.length, incoming_blocks.items, incoming_values.items, peer_parent); } - return ir_lval_wrap(irb, scope, result_instruction, lval, result_loc); + return ir_lval_wrap(ag, scope, result_instruction, lval, result_loc); } -static IrInstSrc *ir_gen_comptime(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node, LVal lval) { +static IrInstSrc *ir_gen_comptime(Stage1AstGen *ag, Scope *parent_scope, AstNode *node, LVal lval) { assert(node->type == NodeTypeCompTime); - Scope *child_scope = create_comptime_scope(irb->codegen, node, parent_scope); + Scope *child_scope = create_comptime_scope(ag->codegen, node, parent_scope); // purposefully pass null for result_loc and let EndExpr handle it - return ir_gen_node_extra(irb, node->data.comptime_expr.expr, child_scope, lval, nullptr); + return ir_gen_node_extra(ag, node->data.comptime_expr.expr, child_scope, lval, nullptr); } -static IrInstSrc *ir_gen_nosuspend(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node, LVal lval) { +static IrInstSrc *ir_gen_nosuspend(Stage1AstGen *ag, Scope *parent_scope, AstNode *node, LVal lval) { assert(node->type == NodeTypeNoSuspend); - Scope *child_scope = create_nosuspend_scope(irb->codegen, node, parent_scope); + Scope *child_scope = create_nosuspend_scope(ag->codegen, node, parent_scope); // purposefully pass null for result_loc and let EndExpr handle it - return ir_gen_node_extra(irb, node->data.nosuspend_expr.expr, child_scope, lval, nullptr); + return ir_gen_node_extra(ag, node->data.nosuspend_expr.expr, child_scope, lval, nullptr); } -static IrInstSrc *ir_gen_return_from_block(IrBuilderSrc *irb, Scope *break_scope, AstNode *node, ScopeBlock *block_scope) { +static IrInstSrc *ir_gen_return_from_block(Stage1AstGen *ag, Scope *break_scope, AstNode *node, ScopeBlock *block_scope) { IrInstSrc *is_comptime; - if (ir_should_inline(irb->exec, break_scope)) { - is_comptime = ir_build_const_bool(irb, break_scope, node, true); + if (ir_should_inline(ag->exec, break_scope)) { + is_comptime = ir_build_const_bool(ag, break_scope, node, true); } else { is_comptime = block_scope->is_comptime; } @@ -7199,24 +7199,24 @@ static IrInstSrc *ir_gen_return_from_block(IrBuilderSrc *irb, Scope *break_scope ResultLocPeer *peer_result = create_peer_result(block_scope->peer_parent); block_scope->peer_parent->peers.append(peer_result); - result_value = ir_gen_node_extra(irb, node->data.break_expr.expr, break_scope, block_scope->lval, + result_value = ir_gen_node_extra(ag, node->data.break_expr.expr, break_scope, block_scope->lval, &peer_result->base); - if (result_value == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; + if (result_value == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; } else { - result_value = ir_build_const_void(irb, break_scope, node); + result_value = ir_build_const_void(ag, break_scope, node); } IrBasicBlockSrc *dest_block = block_scope->end_block; - if (!ir_gen_defers_for_block(irb, break_scope, dest_block->scope, nullptr, nullptr)) - return irb->codegen->invalid_inst_src; + if (!ir_gen_defers_for_block(ag, break_scope, dest_block->scope, nullptr, nullptr)) + return ag->codegen->invalid_inst_src; - block_scope->incoming_blocks->append(irb->current_basic_block); + block_scope->incoming_blocks->append(ag->current_basic_block); block_scope->incoming_values->append(result_value); - return ir_build_br(irb, break_scope, node, dest_block, is_comptime); + return ir_build_br(ag, break_scope, node, dest_block, is_comptime); } -static IrInstSrc *ir_gen_break(IrBuilderSrc *irb, Scope *break_scope, AstNode *node) { +static IrInstSrc *ir_gen_break(Stage1AstGen *ag, Scope *break_scope, AstNode *node) { assert(node->type == NodeTypeBreak); // Search up the scope. We'll find one of these things first: @@ -7230,15 +7230,15 @@ static IrInstSrc *ir_gen_break(IrBuilderSrc *irb, Scope *break_scope, AstNode *n for (;;) { if (search_scope == nullptr || search_scope->id == ScopeIdFnDef) { if (node->data.break_expr.name != nullptr) { - add_node_error(irb->codegen, node, buf_sprintf("label not found: '%s'", buf_ptr(node->data.break_expr.name))); - return irb->codegen->invalid_inst_src; + add_node_error(ag->codegen, node, buf_sprintf("label not found: '%s'", buf_ptr(node->data.break_expr.name))); + return ag->codegen->invalid_inst_src; } else { - add_node_error(irb->codegen, node, buf_sprintf("break expression outside loop")); - return irb->codegen->invalid_inst_src; + add_node_error(ag->codegen, node, buf_sprintf("break expression outside loop")); + return ag->codegen->invalid_inst_src; } } else if (search_scope->id == ScopeIdDeferExpr) { - add_node_error(irb->codegen, node, buf_sprintf("cannot break out of defer expression")); - return irb->codegen->invalid_inst_src; + add_node_error(ag->codegen, node, buf_sprintf("cannot break out of defer expression")); + return ag->codegen->invalid_inst_src; } else if (search_scope->id == ScopeIdLoop) { ScopeLoop *this_loop_scope = (ScopeLoop *)search_scope; if (node->data.break_expr.name == nullptr || @@ -7255,18 +7255,18 @@ static IrInstSrc *ir_gen_break(IrBuilderSrc *irb, Scope *break_scope, AstNode *n { assert(this_block_scope->end_block != nullptr); this_block_scope->name_used = true; - return ir_gen_return_from_block(irb, break_scope, node, this_block_scope); + return ir_gen_return_from_block(ag, break_scope, node, this_block_scope); } } else if (search_scope->id == ScopeIdSuspend) { - add_node_error(irb->codegen, node, buf_sprintf("cannot break out of suspend block")); - return irb->codegen->invalid_inst_src; + add_node_error(ag->codegen, node, buf_sprintf("cannot break out of suspend block")); + return ag->codegen->invalid_inst_src; } search_scope = search_scope->parent; } IrInstSrc *is_comptime; - if (ir_should_inline(irb->exec, break_scope)) { - is_comptime = ir_build_const_bool(irb, break_scope, node, true); + if (ir_should_inline(ag->exec, break_scope)) { + is_comptime = ir_build_const_bool(ag, break_scope, node, true); } else { is_comptime = loop_scope->is_comptime; } @@ -7276,24 +7276,24 @@ static IrInstSrc *ir_gen_break(IrBuilderSrc *irb, Scope *break_scope, AstNode *n ResultLocPeer *peer_result = create_peer_result(loop_scope->peer_parent); loop_scope->peer_parent->peers.append(peer_result); - result_value = ir_gen_node_extra(irb, node->data.break_expr.expr, break_scope, + result_value = ir_gen_node_extra(ag, node->data.break_expr.expr, break_scope, loop_scope->lval, &peer_result->base); - if (result_value == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; + if (result_value == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; } else { - result_value = ir_build_const_void(irb, break_scope, node); + result_value = ir_build_const_void(ag, break_scope, node); } IrBasicBlockSrc *dest_block = loop_scope->break_block; - if (!ir_gen_defers_for_block(irb, break_scope, dest_block->scope, nullptr, nullptr)) - return irb->codegen->invalid_inst_src; + if (!ir_gen_defers_for_block(ag, break_scope, dest_block->scope, nullptr, nullptr)) + return ag->codegen->invalid_inst_src; - loop_scope->incoming_blocks->append(irb->current_basic_block); + loop_scope->incoming_blocks->append(ag->current_basic_block); loop_scope->incoming_values->append(result_value); - return ir_build_br(irb, break_scope, node, dest_block, is_comptime); + return ir_build_br(ag, break_scope, node, dest_block, is_comptime); } -static IrInstSrc *ir_gen_continue(IrBuilderSrc *irb, Scope *continue_scope, AstNode *node) { +static IrInstSrc *ir_gen_continue(Stage1AstGen *ag, Scope *continue_scope, AstNode *node) { assert(node->type == NodeTypeContinue); // Search up the scope. We'll find one of these things first: @@ -7308,15 +7308,15 @@ static IrInstSrc *ir_gen_continue(IrBuilderSrc *irb, Scope *continue_scope, AstN for (;;) { if (search_scope == nullptr || search_scope->id == ScopeIdFnDef) { if (node->data.continue_expr.name != nullptr) { - add_node_error(irb->codegen, node, buf_sprintf("labeled loop not found: '%s'", buf_ptr(node->data.continue_expr.name))); - return irb->codegen->invalid_inst_src; + add_node_error(ag->codegen, node, buf_sprintf("labeled loop not found: '%s'", buf_ptr(node->data.continue_expr.name))); + return ag->codegen->invalid_inst_src; } else { - add_node_error(irb->codegen, node, buf_sprintf("continue expression outside loop")); - return irb->codegen->invalid_inst_src; + add_node_error(ag->codegen, node, buf_sprintf("continue expression outside loop")); + return ag->codegen->invalid_inst_src; } } else if (search_scope->id == ScopeIdDeferExpr) { - add_node_error(irb->codegen, node, buf_sprintf("cannot continue out of defer expression")); - return irb->codegen->invalid_inst_src; + add_node_error(ag->codegen, node, buf_sprintf("cannot continue out of defer expression")); + return ag->codegen->invalid_inst_src; } else if (search_scope->id == ScopeIdLoop) { ScopeLoop *this_loop_scope = (ScopeLoop *)search_scope; if (node->data.continue_expr.name == nullptr || @@ -7334,42 +7334,42 @@ static IrInstSrc *ir_gen_continue(IrBuilderSrc *irb, Scope *continue_scope, AstN } IrInstSrc *is_comptime; - if (ir_should_inline(irb->exec, continue_scope)) { - is_comptime = ir_build_const_bool(irb, continue_scope, node, true); + if (ir_should_inline(ag->exec, continue_scope)) { + is_comptime = ir_build_const_bool(ag, continue_scope, node, true); } else { is_comptime = loop_scope->is_comptime; } for (size_t i = 0; i < runtime_scopes.length; i += 1) { ScopeRuntime *scope_runtime = runtime_scopes.at(i); - ir_mark_gen(ir_build_check_runtime_scope(irb, continue_scope, node, scope_runtime->is_comptime, is_comptime)); + ir_mark_gen(ir_build_check_runtime_scope(ag, continue_scope, node, scope_runtime->is_comptime, is_comptime)); } runtime_scopes.deinit(); IrBasicBlockSrc *dest_block = loop_scope->continue_block; - if (!ir_gen_defers_for_block(irb, continue_scope, dest_block->scope, nullptr, nullptr)) - return irb->codegen->invalid_inst_src; - return ir_mark_gen(ir_build_br(irb, continue_scope, node, dest_block, is_comptime)); + if (!ir_gen_defers_for_block(ag, continue_scope, dest_block->scope, nullptr, nullptr)) + return ag->codegen->invalid_inst_src; + return ir_mark_gen(ir_build_br(ag, continue_scope, node, dest_block, is_comptime)); } -static IrInstSrc *ir_gen_error_type(IrBuilderSrc *irb, Scope *scope, AstNode *node) { +static IrInstSrc *ir_gen_error_type(Stage1AstGen *ag, Scope *scope, AstNode *node) { assert(node->type == NodeTypeErrorType); - return ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_global_error_set); + return ir_build_const_type(ag, scope, node, ag->codegen->builtin_types.entry_global_error_set); } -static IrInstSrc *ir_gen_defer(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node) { +static IrInstSrc *ir_gen_defer(Stage1AstGen *ag, Scope *parent_scope, AstNode *node) { assert(node->type == NodeTypeDefer); - ScopeDefer *defer_child_scope = create_defer_scope(irb->codegen, node, parent_scope); + ScopeDefer *defer_child_scope = create_defer_scope(ag->codegen, node, parent_scope); node->data.defer.child_scope = &defer_child_scope->base; - ScopeDeferExpr *defer_expr_scope = create_defer_expr_scope(irb->codegen, node, parent_scope); + ScopeDeferExpr *defer_expr_scope = create_defer_expr_scope(ag->codegen, node, parent_scope); node->data.defer.expr_scope = &defer_expr_scope->base; - return ir_build_const_void(irb, parent_scope, node); + return ir_build_const_void(ag, parent_scope, node); } -static IrInstSrc *ir_gen_slice(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { +static IrInstSrc *ir_gen_slice(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypeSliceExpr); AstNodeSliceExpr *slice_expr = &node->data.slice_expr; @@ -7378,38 +7378,38 @@ static IrInstSrc *ir_gen_slice(IrBuilderSrc *irb, Scope *scope, AstNode *node, L AstNode *end_node = slice_expr->end; AstNode *sentinel_node = slice_expr->sentinel; - IrInstSrc *ptr_value = ir_gen_node_extra(irb, array_node, scope, LValPtr, nullptr); - if (ptr_value == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; + IrInstSrc *ptr_value = ir_gen_node_extra(ag, array_node, scope, LValPtr, nullptr); + if (ptr_value == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; - IrInstSrc *start_value = ir_gen_node(irb, start_node, scope); - if (start_value == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; + IrInstSrc *start_value = ir_gen_node(ag, start_node, scope); + if (start_value == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; IrInstSrc *end_value; if (end_node) { - end_value = ir_gen_node(irb, end_node, scope); - if (end_value == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; + end_value = ir_gen_node(ag, end_node, scope); + if (end_value == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; } else { end_value = nullptr; } IrInstSrc *sentinel_value; if (sentinel_node) { - sentinel_value = ir_gen_node(irb, sentinel_node, scope); - if (sentinel_value == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; + sentinel_value = ir_gen_node(ag, sentinel_node, scope); + if (sentinel_value == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; } else { sentinel_value = nullptr; } - IrInstSrc *slice = ir_build_slice_src(irb, scope, node, ptr_value, start_value, end_value, + IrInstSrc *slice = ir_build_slice_src(ag, scope, node, ptr_value, start_value, end_value, sentinel_value, true, result_loc); - return ir_lval_wrap(irb, scope, slice, lval, result_loc); + return ir_lval_wrap(ag, scope, slice, lval, result_loc); } -static IrInstSrc *ir_gen_catch(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node, LVal lval, +static IrInstSrc *ir_gen_catch(Stage1AstGen *ag, Scope *parent_scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypeCatchExpr); @@ -7422,77 +7422,77 @@ static IrInstSrc *ir_gen_catch(IrBuilderSrc *irb, Scope *parent_scope, AstNode * if (var_node != nullptr) { assert(var_node->type == NodeTypeIdentifier); Buf *var_name = node_identifier_buf(var_node); - add_node_error(irb->codegen, var_node, buf_sprintf("unused variable: '%s'", buf_ptr(var_name))); - return irb->codegen->invalid_inst_src; + add_node_error(ag->codegen, var_node, buf_sprintf("unused variable: '%s'", buf_ptr(var_name))); + return ag->codegen->invalid_inst_src; } - return ir_gen_catch_unreachable(irb, parent_scope, node, op1_node, lval, result_loc); + return ir_gen_catch_unreachable(ag, parent_scope, node, op1_node, lval, result_loc); } - ScopeExpr *spill_scope = create_expr_scope(irb->codegen, op1_node, parent_scope); + ScopeExpr *spill_scope = create_expr_scope(ag->codegen, op1_node, parent_scope); spill_scope->spill_harder = true; - IrInstSrc *err_union_ptr = ir_gen_node_extra(irb, op1_node, &spill_scope->base, LValPtr, nullptr); - if (err_union_ptr == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; + IrInstSrc *err_union_ptr = ir_gen_node_extra(ag, op1_node, &spill_scope->base, LValPtr, nullptr); + if (err_union_ptr == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; - IrInstSrc *is_err = ir_build_test_err_src(irb, parent_scope, node, err_union_ptr, true, false); + IrInstSrc *is_err = ir_build_test_err_src(ag, parent_scope, node, err_union_ptr, true, false); IrInstSrc *is_comptime; - if (ir_should_inline(irb->exec, parent_scope)) { - is_comptime = ir_build_const_bool(irb, parent_scope, node, true); + if (ir_should_inline(ag->exec, parent_scope)) { + is_comptime = ir_build_const_bool(ag, parent_scope, node, true); } else { - is_comptime = ir_build_test_comptime(irb, parent_scope, node, is_err); + is_comptime = ir_build_test_comptime(ag, parent_scope, node, is_err); } - IrBasicBlockSrc *ok_block = ir_create_basic_block(irb, parent_scope, "UnwrapErrOk"); - IrBasicBlockSrc *err_block = ir_create_basic_block(irb, parent_scope, "UnwrapErrError"); - IrBasicBlockSrc *end_block = ir_create_basic_block(irb, parent_scope, "UnwrapErrEnd"); - IrInstSrc *cond_br_inst = ir_build_cond_br(irb, parent_scope, node, is_err, err_block, ok_block, is_comptime); + IrBasicBlockSrc *ok_block = ir_create_basic_block(ag, parent_scope, "UnwrapErrOk"); + IrBasicBlockSrc *err_block = ir_create_basic_block(ag, parent_scope, "UnwrapErrError"); + IrBasicBlockSrc *end_block = ir_create_basic_block(ag, parent_scope, "UnwrapErrEnd"); + IrInstSrc *cond_br_inst = ir_build_cond_br(ag, parent_scope, node, is_err, err_block, ok_block, is_comptime); - ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, ok_block, end_block, result_loc, + ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(ag, cond_br_inst, ok_block, end_block, result_loc, is_comptime); - ir_set_cursor_at_end_and_append_block(irb, err_block); - Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, &spill_scope->base, is_comptime); + ir_set_cursor_at_end_and_append_block(ag, err_block); + Scope *subexpr_scope = create_runtime_scope(ag->codegen, node, &spill_scope->base, is_comptime); Scope *err_scope; if (var_node) { assert(var_node->type == NodeTypeIdentifier); Buf *var_name = node_identifier_buf(var_node); bool is_const = true; bool is_shadowable = false; - ZigVar *var = ir_create_var(irb, node, subexpr_scope, var_name, + ZigVar *var = ir_create_var(ag, node, subexpr_scope, var_name, is_const, is_const, is_shadowable, is_comptime); err_scope = var->child_scope; - IrInstSrc *err_ptr = ir_build_unwrap_err_code_src(irb, err_scope, node, err_union_ptr); - IrInstSrc *err_value = ir_build_load_ptr(irb, err_scope, var_node, err_ptr); - build_decl_var_and_init(irb, err_scope, var_node, var, err_value, buf_ptr(var_name), is_comptime); + IrInstSrc *err_ptr = ir_build_unwrap_err_code_src(ag, err_scope, node, err_union_ptr); + IrInstSrc *err_value = ir_build_load_ptr(ag, err_scope, var_node, err_ptr); + build_decl_var_and_init(ag, err_scope, var_node, var, err_value, buf_ptr(var_name), is_comptime); } else { err_scope = subexpr_scope; } - IrInstSrc *err_result = ir_gen_node_extra(irb, op2_node, err_scope, LValNone, &peer_parent->peers.at(0)->base); - if (err_result == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - IrBasicBlockSrc *after_err_block = irb->current_basic_block; + IrInstSrc *err_result = ir_gen_node_extra(ag, op2_node, err_scope, LValNone, &peer_parent->peers.at(0)->base); + if (err_result == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; + IrBasicBlockSrc *after_err_block = ag->current_basic_block; if (!instr_is_unreachable(err_result)) - ir_mark_gen(ir_build_br(irb, parent_scope, node, end_block, is_comptime)); + ir_mark_gen(ir_build_br(ag, parent_scope, node, end_block, is_comptime)); - ir_set_cursor_at_end_and_append_block(irb, ok_block); - IrInstSrc *unwrapped_ptr = ir_build_unwrap_err_payload_src(irb, parent_scope, node, err_union_ptr, false, false); - IrInstSrc *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr); - ir_build_end_expr(irb, parent_scope, node, unwrapped_payload, &peer_parent->peers.at(1)->base); - IrBasicBlockSrc *after_ok_block = irb->current_basic_block; - ir_build_br(irb, parent_scope, node, end_block, is_comptime); + ir_set_cursor_at_end_and_append_block(ag, ok_block); + IrInstSrc *unwrapped_ptr = ir_build_unwrap_err_payload_src(ag, parent_scope, node, err_union_ptr, false, false); + IrInstSrc *unwrapped_payload = ir_build_load_ptr(ag, parent_scope, node, unwrapped_ptr); + ir_build_end_expr(ag, parent_scope, node, unwrapped_payload, &peer_parent->peers.at(1)->base); + IrBasicBlockSrc *after_ok_block = ag->current_basic_block; + ir_build_br(ag, parent_scope, node, end_block, is_comptime); - ir_set_cursor_at_end_and_append_block(irb, end_block); + ir_set_cursor_at_end_and_append_block(ag, end_block); IrInstSrc **incoming_values = heap::c_allocator.allocate(2); incoming_values[0] = err_result; incoming_values[1] = unwrapped_payload; IrBasicBlockSrc **incoming_blocks = heap::c_allocator.allocate(2); incoming_blocks[0] = after_err_block; incoming_blocks[1] = after_ok_block; - IrInstSrc *phi = ir_build_phi(irb, parent_scope, node, 2, incoming_blocks, incoming_values, peer_parent); - return ir_lval_wrap(irb, parent_scope, phi, lval, result_loc); + IrInstSrc *phi = ir_build_phi(ag, parent_scope, node, 2, incoming_blocks, incoming_values, peer_parent); + return ir_lval_wrap(ag, parent_scope, phi, lval, result_loc); } static bool render_instance_name_recursive(CodeGen *codegen, Buf *name, Scope *outer_scope, Scope *inner_scope) { @@ -7540,51 +7540,51 @@ Buf *get_anon_type_name(CodeGen *codegen, Stage1Zir *exec, const char *kind_name } } -static IrInstSrc *ir_gen_container_decl(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node) { +static IrInstSrc *ir_gen_container_decl(Stage1AstGen *ag, Scope *parent_scope, AstNode *node) { assert(node->type == NodeTypeContainerDecl); ContainerKind kind = node->data.container_decl.kind; Buf *bare_name = buf_alloc(); - Buf *name = get_anon_type_name(irb->codegen, irb->exec, container_string(kind), parent_scope, node, bare_name); + Buf *name = get_anon_type_name(ag->codegen, ag->exec, container_string(kind), parent_scope, node, bare_name); ContainerLayout layout = node->data.container_decl.layout; - ZigType *container_type = get_partial_container_type(irb->codegen, parent_scope, + ZigType *container_type = get_partial_container_type(ag->codegen, parent_scope, kind, node, buf_ptr(name), bare_name, layout); ScopeDecls *child_scope = get_container_scope(container_type); for (size_t i = 0; i < node->data.container_decl.decls.length; i += 1) { AstNode *child_node = node->data.container_decl.decls.at(i); - scan_decls(irb->codegen, child_scope, child_node); + scan_decls(ag->codegen, child_scope, child_node); } TldContainer *tld_container = heap::c_allocator.create(); init_tld(&tld_container->base, TldIdContainer, bare_name, VisibModPub, node, parent_scope); tld_container->type_entry = container_type; tld_container->decls_scope = child_scope; - irb->codegen->resolve_queue.append(&tld_container->base); + ag->codegen->resolve_queue.append(&tld_container->base); // Add this to the list to mark as invalid if analyzing this exec fails. - irb->exec->tld_list.append(&tld_container->base); + ag->exec->tld_list.append(&tld_container->base); - return ir_build_const_type(irb, parent_scope, node, container_type); + return ir_build_const_type(ag, parent_scope, node, container_type); } -static IrInstSrc *ir_gen_err_set_decl(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node) { +static IrInstSrc *ir_gen_err_set_decl(Stage1AstGen *ag, Scope *parent_scope, AstNode *node) { assert(node->type == NodeTypeErrorSetDecl); uint32_t err_count = node->data.err_set_decl.decls.length; Buf bare_name = BUF_INIT; - Buf *type_name = get_anon_type_name(irb->codegen, irb->exec, "error", parent_scope, node, &bare_name); + Buf *type_name = get_anon_type_name(ag->codegen, ag->exec, "error", parent_scope, node, &bare_name); ZigType *err_set_type = new_type_table_entry(ZigTypeIdErrorSet); buf_init_from_buf(&err_set_type->name, type_name); err_set_type->data.error_set.err_count = err_count; - err_set_type->size_in_bits = irb->codegen->builtin_types.entry_global_error_set->size_in_bits; - err_set_type->abi_align = irb->codegen->builtin_types.entry_global_error_set->abi_align; - err_set_type->abi_size = irb->codegen->builtin_types.entry_global_error_set->abi_size; + err_set_type->size_in_bits = ag->codegen->builtin_types.entry_global_error_set->size_in_bits; + err_set_type->abi_align = ag->codegen->builtin_types.entry_global_error_set->abi_align; + err_set_type->abi_size = ag->codegen->builtin_types.entry_global_error_set->abi_size; err_set_type->data.error_set.errors = heap::c_allocator.allocate(err_count); - size_t errors_count = irb->codegen->errors_by_index.length + err_count; + size_t errors_count = ag->codegen->errors_by_index.length + err_count; ErrorTableEntry **errors = heap::c_allocator.allocate(errors_count); for (uint32_t i = 0; i < err_count; i += 1) { @@ -7595,32 +7595,32 @@ static IrInstSrc *ir_gen_err_set_decl(IrBuilderSrc *irb, Scope *parent_scope, As err->decl_node = field_node; buf_init_from_buf(&err->name, err_name); - auto existing_entry = irb->codegen->error_table.put_unique(err_name, err); + auto existing_entry = ag->codegen->error_table.put_unique(err_name, err); if (existing_entry) { err->value = existing_entry->value->value; } else { - size_t error_value_count = irb->codegen->errors_by_index.length; - assert((uint32_t)error_value_count < (((uint32_t)1) << (uint32_t)irb->codegen->err_tag_type->data.integral.bit_count)); + size_t error_value_count = ag->codegen->errors_by_index.length; + assert((uint32_t)error_value_count < (((uint32_t)1) << (uint32_t)ag->codegen->err_tag_type->data.integral.bit_count)); err->value = error_value_count; - irb->codegen->errors_by_index.append(err); + ag->codegen->errors_by_index.append(err); } err_set_type->data.error_set.errors[i] = err; ErrorTableEntry *prev_err = errors[err->value]; if (prev_err != nullptr) { - ErrorMsg *msg = add_node_error(irb->codegen, ast_field_to_symbol_node(err->decl_node), + ErrorMsg *msg = add_node_error(ag->codegen, ast_field_to_symbol_node(err->decl_node), buf_sprintf("duplicate error: '%s'", buf_ptr(&err->name))); - add_error_note(irb->codegen, msg, ast_field_to_symbol_node(prev_err->decl_node), + add_error_note(ag->codegen, msg, ast_field_to_symbol_node(prev_err->decl_node), buf_sprintf("other error here")); - return irb->codegen->invalid_inst_src; + return ag->codegen->invalid_inst_src; } errors[err->value] = err; } heap::c_allocator.deallocate(errors, errors_count); - return ir_build_const_type(irb, parent_scope, node, err_set_type); + return ir_build_const_type(ag, parent_scope, node, err_set_type); } -static IrInstSrc *ir_gen_fn_proto(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node) { +static IrInstSrc *ir_gen_fn_proto(Stage1AstGen *ag, Scope *parent_scope, AstNode *node) { assert(node->type == NodeTypeFnProto); size_t param_count = node->data.fn_proto.params.length; @@ -7635,9 +7635,9 @@ static IrInstSrc *ir_gen_fn_proto(IrBuilderSrc *irb, Scope *parent_scope, AstNod } if (param_node->data.param_decl.anytype_token == 0) { AstNode *type_node = param_node->data.param_decl.type; - IrInstSrc *type_value = ir_gen_node(irb, type_node, parent_scope); - if (type_value == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; + IrInstSrc *type_value = ir_gen_node(ag, type_node, parent_scope); + if (type_value == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; param_types[i] = type_value; } else { param_types[i] = nullptr; @@ -7646,41 +7646,41 @@ static IrInstSrc *ir_gen_fn_proto(IrBuilderSrc *irb, Scope *parent_scope, AstNod IrInstSrc *align_value = nullptr; if (node->data.fn_proto.align_expr != nullptr) { - align_value = ir_gen_node(irb, node->data.fn_proto.align_expr, parent_scope); - if (align_value == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; + align_value = ir_gen_node(ag, node->data.fn_proto.align_expr, parent_scope); + if (align_value == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; } IrInstSrc *callconv_value = nullptr; if (node->data.fn_proto.callconv_expr != nullptr) { - callconv_value = ir_gen_node(irb, node->data.fn_proto.callconv_expr, parent_scope); - if (callconv_value == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; + callconv_value = ir_gen_node(ag, node->data.fn_proto.callconv_expr, parent_scope); + if (callconv_value == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; } IrInstSrc *return_type; if (node->data.fn_proto.return_type == nullptr) { - return_type = ir_build_const_type(irb, parent_scope, node, irb->codegen->builtin_types.entry_void); + return_type = ir_build_const_type(ag, parent_scope, node, ag->codegen->builtin_types.entry_void); } else { - return_type = ir_gen_node(irb, node->data.fn_proto.return_type, parent_scope); - if (return_type == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; + return_type = ir_gen_node(ag, node->data.fn_proto.return_type, parent_scope); + if (return_type == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; } - return ir_build_fn_proto(irb, parent_scope, node, param_types, align_value, callconv_value, return_type, is_var_args); + return ir_build_fn_proto(ag, parent_scope, node, param_types, align_value, callconv_value, return_type, is_var_args); } -static IrInstSrc *ir_gen_resume(IrBuilderSrc *irb, Scope *scope, AstNode *node) { +static IrInstSrc *ir_gen_resume(Stage1AstGen *ag, Scope *scope, AstNode *node) { assert(node->type == NodeTypeResume); - IrInstSrc *target_inst = ir_gen_node_extra(irb, node->data.resume_expr.expr, scope, LValPtr, nullptr); - if (target_inst == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; + IrInstSrc *target_inst = ir_gen_node_extra(ag, node->data.resume_expr.expr, scope, LValPtr, nullptr); + if (target_inst == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; - return ir_build_resume_src(irb, scope, node, target_inst); + return ir_build_resume_src(ag, scope, node, target_inst); } -static IrInstSrc *ir_gen_await_expr(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, +static IrInstSrc *ir_gen_await_expr(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypeAwaitExpr); @@ -7691,73 +7691,73 @@ static IrInstSrc *ir_gen_await_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no if (expr_node->type == NodeTypeFnCallExpr && expr_node->data.fn_call_expr.modifier == CallModifierBuiltin) { AstNode *fn_ref_expr = expr_node->data.fn_call_expr.fn_ref_expr; Buf *name = node_identifier_buf(fn_ref_expr); - auto entry = irb->codegen->builtin_fn_table.maybe_get(name); + auto entry = ag->codegen->builtin_fn_table.maybe_get(name); if (entry != nullptr) { BuiltinFnEntry *builtin_fn = entry->value; if (builtin_fn->id == BuiltinFnIdAsyncCall) { - return ir_gen_async_call(irb, scope, node, expr_node, lval, result_loc); + return ir_gen_async_call(ag, scope, node, expr_node, lval, result_loc); } } } - ZigFn *fn_entry = exec_fn_entry(irb->exec); + ZigFn *fn_entry = exec_fn_entry(ag->exec); if (!fn_entry) { - add_node_error(irb->codegen, node, buf_sprintf("await outside function definition")); - return irb->codegen->invalid_inst_src; + add_node_error(ag->codegen, node, buf_sprintf("await outside function definition")); + return ag->codegen->invalid_inst_src; } ScopeSuspend *existing_suspend_scope = get_scope_suspend(scope); if (existing_suspend_scope) { if (!existing_suspend_scope->reported_err) { - ErrorMsg *msg = add_node_error(irb->codegen, node, buf_sprintf("cannot await inside suspend block")); - add_error_note(irb->codegen, msg, existing_suspend_scope->base.source_node, buf_sprintf("suspend block here")); + ErrorMsg *msg = add_node_error(ag->codegen, node, buf_sprintf("cannot await inside suspend block")); + add_error_note(ag->codegen, msg, existing_suspend_scope->base.source_node, buf_sprintf("suspend block here")); existing_suspend_scope->reported_err = true; } - return irb->codegen->invalid_inst_src; + return ag->codegen->invalid_inst_src; } - IrInstSrc *target_inst = ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr); - if (target_inst == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; + IrInstSrc *target_inst = ir_gen_node_extra(ag, expr_node, scope, LValPtr, nullptr); + if (target_inst == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; - IrInstSrc *await_inst = ir_build_await_src(irb, scope, node, target_inst, result_loc, is_nosuspend); - return ir_lval_wrap(irb, scope, await_inst, lval, result_loc); + IrInstSrc *await_inst = ir_build_await_src(ag, scope, node, target_inst, result_loc, is_nosuspend); + return ir_lval_wrap(ag, scope, await_inst, lval, result_loc); } -static IrInstSrc *ir_gen_suspend(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node) { +static IrInstSrc *ir_gen_suspend(Stage1AstGen *ag, Scope *parent_scope, AstNode *node) { assert(node->type == NodeTypeSuspend); - ZigFn *fn_entry = exec_fn_entry(irb->exec); + ZigFn *fn_entry = exec_fn_entry(ag->exec); if (!fn_entry) { - add_node_error(irb->codegen, node, buf_sprintf("suspend outside function definition")); - return irb->codegen->invalid_inst_src; + add_node_error(ag->codegen, node, buf_sprintf("suspend outside function definition")); + return ag->codegen->invalid_inst_src; } if (get_scope_nosuspend(parent_scope) != nullptr) { - add_node_error(irb->codegen, node, buf_sprintf("suspend in nosuspend scope")); - return irb->codegen->invalid_inst_src; + add_node_error(ag->codegen, node, buf_sprintf("suspend in nosuspend scope")); + return ag->codegen->invalid_inst_src; } ScopeSuspend *existing_suspend_scope = get_scope_suspend(parent_scope); if (existing_suspend_scope) { if (!existing_suspend_scope->reported_err) { - ErrorMsg *msg = add_node_error(irb->codegen, node, buf_sprintf("cannot suspend inside suspend block")); - add_error_note(irb->codegen, msg, existing_suspend_scope->base.source_node, buf_sprintf("other suspend block here")); + ErrorMsg *msg = add_node_error(ag->codegen, node, buf_sprintf("cannot suspend inside suspend block")); + add_error_note(ag->codegen, msg, existing_suspend_scope->base.source_node, buf_sprintf("other suspend block here")); existing_suspend_scope->reported_err = true; } - return irb->codegen->invalid_inst_src; + return ag->codegen->invalid_inst_src; } - IrInstSrcSuspendBegin *begin = ir_build_suspend_begin_src(irb, parent_scope, node); - ScopeSuspend *suspend_scope = create_suspend_scope(irb->codegen, node, parent_scope); + IrInstSrcSuspendBegin *begin = ir_build_suspend_begin_src(ag, parent_scope, node); + ScopeSuspend *suspend_scope = create_suspend_scope(ag->codegen, node, parent_scope); Scope *child_scope = &suspend_scope->base; - IrInstSrc *susp_res = ir_gen_node(irb, node->data.suspend.block, child_scope); - if (susp_res == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; - ir_mark_gen(ir_build_check_statement_is_void(irb, child_scope, node->data.suspend.block, susp_res)); + IrInstSrc *susp_res = ir_gen_node(ag, node->data.suspend.block, child_scope); + if (susp_res == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; + ir_mark_gen(ir_build_check_statement_is_void(ag, child_scope, node->data.suspend.block, susp_res)); - return ir_mark_gen(ir_build_suspend_finish_src(irb, parent_scope, node, begin)); + return ir_mark_gen(ir_build_suspend_finish_src(ag, parent_scope, node, begin)); } -static IrInstSrc *ir_gen_node_raw(IrBuilderSrc *irb, AstNode *node, Scope *scope, +static IrInstSrc *ir_gen_node_raw(Stage1AstGen *ag, AstNode *node, Scope *scope, LVal lval, ResultLoc *result_loc) { assert(scope); @@ -7773,47 +7773,47 @@ static IrInstSrc *ir_gen_node_raw(IrBuilderSrc *irb, AstNode *node, Scope *scope case NodeTypeTestDecl: zig_unreachable(); case NodeTypeBlock: - return ir_gen_block(irb, scope, node, lval, result_loc); + return ir_gen_block(ag, scope, node, lval, result_loc); case NodeTypeGroupedExpr: - return ir_gen_node_raw(irb, node->data.grouped_expr, scope, lval, result_loc); + return ir_gen_node_raw(ag, node->data.grouped_expr, scope, lval, result_loc); case NodeTypeBinOpExpr: - return ir_gen_bin_op(irb, scope, node, lval, result_loc); + return ir_gen_bin_op(ag, scope, node, lval, result_loc); case NodeTypeIntLiteral: - return ir_lval_wrap(irb, scope, ir_gen_int_lit(irb, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_int_lit(ag, scope, node), lval, result_loc); case NodeTypeFloatLiteral: - return ir_lval_wrap(irb, scope, ir_gen_float_lit(irb, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_float_lit(ag, scope, node), lval, result_loc); case NodeTypeCharLiteral: - return ir_lval_wrap(irb, scope, ir_gen_char_lit(irb, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_char_lit(ag, scope, node), lval, result_loc); case NodeTypeIdentifier: - return ir_gen_symbol(irb, scope, node, lval, result_loc); + return ir_gen_symbol(ag, scope, node, lval, result_loc); case NodeTypeFnCallExpr: - return ir_gen_fn_call(irb, scope, node, lval, result_loc); + return ir_gen_fn_call(ag, scope, node, lval, result_loc); case NodeTypeIfBoolExpr: - return ir_gen_if_bool_expr(irb, scope, node, lval, result_loc); + return ir_gen_if_bool_expr(ag, scope, node, lval, result_loc); case NodeTypePrefixOpExpr: - return ir_gen_prefix_op_expr(irb, scope, node, lval, result_loc); + return ir_gen_prefix_op_expr(ag, scope, node, lval, result_loc); case NodeTypeContainerInitExpr: - return ir_gen_container_init_expr(irb, scope, node, lval, result_loc); + return ir_gen_container_init_expr(ag, scope, node, lval, result_loc); case NodeTypeVariableDeclaration: - return ir_gen_var_decl(irb, scope, node); + return ir_gen_var_decl(ag, scope, node); case NodeTypeWhileExpr: - return ir_gen_while_expr(irb, scope, node, lval, result_loc); + return ir_gen_while_expr(ag, scope, node, lval, result_loc); case NodeTypeForExpr: - return ir_gen_for_expr(irb, scope, node, lval, result_loc); + return ir_gen_for_expr(ag, scope, node, lval, result_loc); case NodeTypeArrayAccessExpr: - return ir_gen_array_access(irb, scope, node, lval, result_loc); + return ir_gen_array_access(ag, scope, node, lval, result_loc); case NodeTypeReturnExpr: - return ir_gen_return(irb, scope, node, lval, result_loc); + return ir_gen_return(ag, scope, node, lval, result_loc); case NodeTypeFieldAccessExpr: { - IrInstSrc *ptr_instruction = ir_gen_field_access(irb, scope, node); - if (ptr_instruction == irb->codegen->invalid_inst_src) + IrInstSrc *ptr_instruction = ir_gen_field_access(ag, scope, node); + if (ptr_instruction == ag->codegen->invalid_inst_src) return ptr_instruction; if (lval == LValPtr || lval == LValAssign) return ptr_instruction; - IrInstSrc *load_ptr = ir_build_load_ptr(irb, scope, node, ptr_instruction); - return ir_expr_wrap(irb, scope, load_ptr, result_loc); + IrInstSrc *load_ptr = ir_build_load_ptr(ag, scope, node, ptr_instruction); + return ir_expr_wrap(ag, scope, load_ptr, result_loc); } case NodeTypePtrDeref: { AstNode *expr_node = node->data.ptr_deref_expr.target; @@ -7822,91 +7822,91 @@ static IrInstSrc *ir_gen_node_raw(IrBuilderSrc *irb, AstNode *node, Scope *scope if (child_lval == LValAssign) child_lval = LValPtr; - IrInstSrc *value = ir_gen_node_extra(irb, expr_node, scope, child_lval, nullptr); - if (value == irb->codegen->invalid_inst_src) + IrInstSrc *value = ir_gen_node_extra(ag, expr_node, scope, child_lval, nullptr); + if (value == ag->codegen->invalid_inst_src) return value; // We essentially just converted any lvalue from &(x.*) to (&x).*; // this inhibits checking that x is a pointer later, so we directly // record whether the pointer check is needed - IrInstSrc *un_op = ir_build_un_op_lval(irb, scope, node, IrUnOpDereference, value, lval, result_loc); - return ir_expr_wrap(irb, scope, un_op, result_loc); + IrInstSrc *un_op = ir_build_un_op_lval(ag, scope, node, IrUnOpDereference, value, lval, result_loc); + return ir_expr_wrap(ag, scope, un_op, result_loc); } case NodeTypeUnwrapOptional: { AstNode *expr_node = node->data.unwrap_optional.expr; - IrInstSrc *maybe_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr); - if (maybe_ptr == irb->codegen->invalid_inst_src) - return irb->codegen->invalid_inst_src; + IrInstSrc *maybe_ptr = ir_gen_node_extra(ag, expr_node, scope, LValPtr, nullptr); + if (maybe_ptr == ag->codegen->invalid_inst_src) + return ag->codegen->invalid_inst_src; - IrInstSrc *unwrapped_ptr = ir_build_optional_unwrap_ptr(irb, scope, node, maybe_ptr, true ); + IrInstSrc *unwrapped_ptr = ir_build_optional_unwrap_ptr(ag, scope, node, maybe_ptr, true ); if (lval == LValPtr || lval == LValAssign) return unwrapped_ptr; - IrInstSrc *load_ptr = ir_build_load_ptr(irb, scope, node, unwrapped_ptr); - return ir_expr_wrap(irb, scope, load_ptr, result_loc); + IrInstSrc *load_ptr = ir_build_load_ptr(ag, scope, node, unwrapped_ptr); + return ir_expr_wrap(ag, scope, load_ptr, result_loc); } case NodeTypeBoolLiteral: - return ir_lval_wrap(irb, scope, ir_gen_bool_literal(irb, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_bool_literal(ag, scope, node), lval, result_loc); case NodeTypeArrayType: - return ir_lval_wrap(irb, scope, ir_gen_array_type(irb, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_array_type(ag, scope, node), lval, result_loc); case NodeTypePointerType: - return ir_lval_wrap(irb, scope, ir_gen_pointer_type(irb, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_pointer_type(ag, scope, node), lval, result_loc); case NodeTypeAnyFrameType: - return ir_lval_wrap(irb, scope, ir_gen_anyframe_type(irb, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_anyframe_type(ag, scope, node), lval, result_loc); case NodeTypeStringLiteral: - return ir_lval_wrap(irb, scope, ir_gen_string_literal(irb, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_string_literal(ag, scope, node), lval, result_loc); case NodeTypeUndefinedLiteral: - return ir_lval_wrap(irb, scope, ir_gen_undefined_literal(irb, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_undefined_literal(ag, scope, node), lval, result_loc); case NodeTypeAsmExpr: - return ir_lval_wrap(irb, scope, ir_gen_asm_expr(irb, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_asm_expr(ag, scope, node), lval, result_loc); case NodeTypeNullLiteral: - return ir_lval_wrap(irb, scope, ir_gen_null_literal(irb, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_null_literal(ag, scope, node), lval, result_loc); case NodeTypeIfErrorExpr: - return ir_gen_if_err_expr(irb, scope, node, lval, result_loc); + return ir_gen_if_err_expr(ag, scope, node, lval, result_loc); case NodeTypeIfOptional: - return ir_gen_if_optional_expr(irb, scope, node, lval, result_loc); + return ir_gen_if_optional_expr(ag, scope, node, lval, result_loc); case NodeTypeSwitchExpr: - return ir_gen_switch_expr(irb, scope, node, lval, result_loc); + return ir_gen_switch_expr(ag, scope, node, lval, result_loc); case NodeTypeCompTime: - return ir_expr_wrap(irb, scope, ir_gen_comptime(irb, scope, node, lval), result_loc); + return ir_expr_wrap(ag, scope, ir_gen_comptime(ag, scope, node, lval), result_loc); case NodeTypeNoSuspend: - return ir_expr_wrap(irb, scope, ir_gen_nosuspend(irb, scope, node, lval), result_loc); + return ir_expr_wrap(ag, scope, ir_gen_nosuspend(ag, scope, node, lval), result_loc); case NodeTypeErrorType: - return ir_lval_wrap(irb, scope, ir_gen_error_type(irb, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_error_type(ag, scope, node), lval, result_loc); case NodeTypeBreak: - return ir_lval_wrap(irb, scope, ir_gen_break(irb, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_break(ag, scope, node), lval, result_loc); case NodeTypeContinue: - return ir_lval_wrap(irb, scope, ir_gen_continue(irb, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_continue(ag, scope, node), lval, result_loc); case NodeTypeUnreachable: - return ir_build_unreachable(irb, scope, node); + return ir_build_unreachable(ag, scope, node); case NodeTypeDefer: - return ir_lval_wrap(irb, scope, ir_gen_defer(irb, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_defer(ag, scope, node), lval, result_loc); case NodeTypeSliceExpr: - return ir_gen_slice(irb, scope, node, lval, result_loc); + return ir_gen_slice(ag, scope, node, lval, result_loc); case NodeTypeCatchExpr: - return ir_gen_catch(irb, scope, node, lval, result_loc); + return ir_gen_catch(ag, scope, node, lval, result_loc); case NodeTypeContainerDecl: - return ir_lval_wrap(irb, scope, ir_gen_container_decl(irb, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_container_decl(ag, scope, node), lval, result_loc); case NodeTypeFnProto: - return ir_lval_wrap(irb, scope, ir_gen_fn_proto(irb, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_fn_proto(ag, scope, node), lval, result_loc); case NodeTypeErrorSetDecl: - return ir_lval_wrap(irb, scope, ir_gen_err_set_decl(irb, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_err_set_decl(ag, scope, node), lval, result_loc); case NodeTypeResume: - return ir_lval_wrap(irb, scope, ir_gen_resume(irb, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_resume(ag, scope, node), lval, result_loc); case NodeTypeAwaitExpr: - return ir_gen_await_expr(irb, scope, node, lval, result_loc); + return ir_gen_await_expr(ag, scope, node, lval, result_loc); case NodeTypeSuspend: - return ir_lval_wrap(irb, scope, ir_gen_suspend(irb, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_suspend(ag, scope, node), lval, result_loc); case NodeTypeEnumLiteral: - return ir_lval_wrap(irb, scope, ir_gen_enum_literal(irb, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, ir_gen_enum_literal(ag, scope, node), lval, result_loc); case NodeTypeInferredArrayType: - add_node_error(irb->codegen, node, + add_node_error(ag->codegen, node, buf_sprintf("inferred array size invalid here")); - return irb->codegen->invalid_inst_src; + return ag->codegen->invalid_inst_src; case NodeTypeAnyTypeField: - return ir_lval_wrap(irb, scope, - ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_anytype), lval, result_loc); + return ir_lval_wrap(ag, scope, + ir_build_const_type(ag, scope, node, ag->codegen->builtin_types.entry_anytype), lval, result_loc); } zig_unreachable(); } @@ -7917,7 +7917,7 @@ ResultLoc *no_result_loc(void) { return &result_loc_none->base; } -static IrInstSrc *ir_gen_node_extra(IrBuilderSrc *irb, AstNode *node, Scope *scope, LVal lval, +static IrInstSrc *ir_gen_node_extra(Stage1AstGen *ag, AstNode *node, Scope *scope, LVal lval, ResultLoc *result_loc) { if (lval == LValAssign) { @@ -7976,30 +7976,30 @@ static IrInstSrc *ir_gen_node_extra(IrBuilderSrc *irb, AstNode *node, Scope *sco case NodeTypeInferredArrayType: case NodeTypeAnyTypeField: case NodeTypePrefixOpExpr: - add_node_error(irb->codegen, node, + add_node_error(ag->codegen, node, buf_sprintf("invalid left-hand side to assignment")); - return irb->codegen->invalid_inst_src; + return ag->codegen->invalid_inst_src; // @field can be assigned to case NodeTypeFnCallExpr: if (node->data.fn_call_expr.modifier == CallModifierBuiltin) { AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr; Buf *name = node_identifier_buf(fn_ref_expr); - auto entry = irb->codegen->builtin_fn_table.maybe_get(name); + auto entry = ag->codegen->builtin_fn_table.maybe_get(name); if (!entry) { - add_node_error(irb->codegen, node, + add_node_error(ag->codegen, node, buf_sprintf("invalid builtin function: '%s'", buf_ptr(name))); - return irb->codegen->invalid_inst_src; + return ag->codegen->invalid_inst_src; } if (entry->value->id == BuiltinFnIdField) { break; } } - add_node_error(irb->codegen, node, + add_node_error(ag->codegen, node, buf_sprintf("invalid left-hand side to assignment")); - return irb->codegen->invalid_inst_src; + return ag->codegen->invalid_inst_src; // can be assigned to @@ -8015,62 +8015,62 @@ static IrInstSrc *ir_gen_node_extra(IrBuilderSrc *irb, AstNode *node, Scope *sco // Create a result location indicating there is none - but if one gets created // it will be properly distributed. result_loc = no_result_loc(); - ir_build_reset_result(irb, scope, node, result_loc); + ir_build_reset_result(ag, scope, node, result_loc); } Scope *child_scope; - if (irb->exec->is_inline || - (irb->exec->fn_entry != nullptr && irb->exec->fn_entry->child_scope == scope)) + if (ag->exec->is_inline || + (ag->exec->fn_entry != nullptr && ag->exec->fn_entry->child_scope == scope)) { child_scope = scope; } else { - child_scope = &create_expr_scope(irb->codegen, node, scope)->base; + child_scope = &create_expr_scope(ag->codegen, node, scope)->base; } - IrInstSrc *result = ir_gen_node_raw(irb, node, child_scope, lval, result_loc); - if (result == irb->codegen->invalid_inst_src) { - if (irb->exec->first_err_trace_msg == nullptr) { - irb->exec->first_err_trace_msg = irb->codegen->trace_err; + IrInstSrc *result = ir_gen_node_raw(ag, node, child_scope, lval, result_loc); + if (result == ag->codegen->invalid_inst_src) { + if (ag->exec->first_err_trace_msg == nullptr) { + ag->exec->first_err_trace_msg = ag->codegen->trace_err; } } return result; } -static IrInstSrc *ir_gen_node(IrBuilderSrc *irb, AstNode *node, Scope *scope) { - return ir_gen_node_extra(irb, node, scope, LValNone, nullptr); +static IrInstSrc *ir_gen_node(Stage1AstGen *ag, AstNode *node, Scope *scope) { + return ir_gen_node_extra(ag, node, scope, LValNone, nullptr); } bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, Stage1Zir *ir_executable) { assert(node->owner); - IrBuilderSrc ir_builder = {0}; - IrBuilderSrc *irb = &ir_builder; + Stage1AstGen ir_builder = {0}; + Stage1AstGen *ag = &ir_builder; - irb->codegen = codegen; - irb->exec = ir_executable; - irb->main_block_node = node; + ag->codegen = codegen; + ag->exec = ir_executable; + ag->main_block_node = node; - IrBasicBlockSrc *entry_block = ir_create_basic_block(irb, scope, "Entry"); - ir_set_cursor_at_end_and_append_block(irb, entry_block); + IrBasicBlockSrc *entry_block = ir_create_basic_block(ag, scope, "Entry"); + ir_set_cursor_at_end_and_append_block(ag, entry_block); // Entry block gets a reference because we enter it to begin. - ir_ref_bb(irb->current_basic_block); + ir_ref_bb(ag->current_basic_block); - IrInstSrc *result = ir_gen_node_extra(irb, node, scope, LValNone, nullptr); + IrInstSrc *result = ir_gen_node_extra(ag, node, scope, LValNone, nullptr); - if (result == irb->codegen->invalid_inst_src) + if (result == ag->codegen->invalid_inst_src) return false; - if (irb->exec->first_err_trace_msg != nullptr) { - codegen->trace_err = irb->exec->first_err_trace_msg; + if (ag->exec->first_err_trace_msg != nullptr) { + codegen->trace_err = ag->exec->first_err_trace_msg; return false; } if (!instr_is_unreachable(result)) { - ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, result->base.source_node, result, nullptr)); + ir_mark_gen(ir_build_add_implicit_return_type(ag, scope, result->base.source_node, result, nullptr)); // no need for save_err_ret_addr because this cannot return error ResultLocReturn *result_loc_ret = heap::c_allocator.create(); result_loc_ret->base.id = ResultLocIdReturn; - ir_build_reset_result(irb, scope, node, &result_loc_ret->base); - ir_mark_gen(ir_build_end_expr(irb, scope, node, result, &result_loc_ret->base)); - ir_mark_gen(ir_build_return_src(irb, scope, result->base.source_node, result)); + ir_build_reset_result(ag, scope, node, &result_loc_ret->base); + ir_mark_gen(ir_build_end_expr(ag, scope, node, result, &result_loc_ret->base)); + ir_mark_gen(ir_build_return_src(ag, scope, result->base.source_node, result)); } return true; From 4ea421f8cb3afc01f6822227b48123dd4844ec07 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 27 May 2021 21:01:03 -0700 Subject: [PATCH 07/14] stage1: move the ZigFn from Stage1Zir to Stage1AstGen Part of an effort to make Stage1Zir immutable. --- src/stage1/all_types.hpp | 2 -- src/stage1/analyze.cpp | 7 ++--- src/stage1/astgen.cpp | 38 ++++++++++++--------------- src/stage1/astgen.hpp | 4 +-- src/stage1/ir.cpp | 55 ++++++++++++++++++++-------------------- src/stage1/ir.hpp | 4 +-- src/stage1/ir_print.cpp | 1 + 7 files changed, 51 insertions(+), 60 deletions(-) diff --git a/src/stage1/all_types.hpp b/src/stage1/all_types.hpp index 90913ed6be..249ca34b1f 100644 --- a/src/stage1/all_types.hpp +++ b/src/stage1/all_types.hpp @@ -114,7 +114,6 @@ struct Stage1Zir { ZigList basic_block_list; Buf *name; ZigFn *name_fn; - ZigFn *fn_entry; Buf *c_import_buf; AstNode *source_node; Scope *begin_scope; @@ -135,7 +134,6 @@ struct Stage1Air { ZigFn *name_fn; size_t mem_slot_count; size_t next_debug_id; - ZigFn *fn_entry; Buf *c_import_buf; AstNode *source_node; Stage1Air *parent_exec; diff --git a/src/stage1/analyze.cpp b/src/stage1/analyze.cpp index dc17cfb493..64ad75a2ad 100644 --- a/src/stage1/analyze.cpp +++ b/src/stage1/analyze.cpp @@ -3654,9 +3654,6 @@ static void get_fully_qualified_decl_name(CodeGen *g, Buf *buf, Tld *tld, bool i static ZigFn *create_fn_raw(CodeGen *g, bool is_noinline) { ZigFn *fn_entry = heap::c_allocator.create(); fn_entry->ir_executable = heap::c_allocator.create(); - - fn_entry->analyzed_executable.fn_entry = fn_entry; - fn_entry->ir_executable->fn_entry = fn_entry; fn_entry->is_noinline = is_noinline; return fn_entry; @@ -5134,7 +5131,7 @@ static void analyze_fn_ir(CodeGen *g, ZigFn *fn, AstNode *return_type_node) { size_t backward_branch_quota = max(fn->branch_quota, default_backward_branch_quota); ZigType *block_return_type = ir_analyze(g, fn->ir_executable, &fn->analyzed_executable, &backward_branch_count, &backward_branch_quota, - fn_type_id->return_type, return_type_node, nullptr); + fn_type_id->return_type, return_type_node, nullptr, fn); fn->src_implicit_return_type = block_return_type; if (type_is_invalid(block_return_type) || fn->analyzed_executable.first_err_trace_msg != nullptr) { @@ -5231,7 +5228,7 @@ static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry) { ZigType *fn_type = fn_table_entry->type_entry; assert(!fn_type->data.fn.is_generic); - if (!ir_gen_fn(g, fn_table_entry)) { + if (!stage1_astgen_fn(g, fn_table_entry)) { fn_table_entry->anal_state = FnAnalStateInvalid; return; } diff --git a/src/stage1/astgen.cpp b/src/stage1/astgen.cpp index a14eb02cc2..a82f156cda 100644 --- a/src/stage1/astgen.cpp +++ b/src/stage1/astgen.cpp @@ -17,6 +17,7 @@ struct Stage1AstGen { IrBasicBlockSrc *current_basic_block; AstNode *main_block_node; size_t next_debug_id; + ZigFn *fn; }; static IrInstSrc *ir_gen_node(Stage1AstGen *ag, AstNode *node, Scope *scope); @@ -368,10 +369,6 @@ static size_t irb_next_debug_id(Stage1AstGen *ag) { return result; } -static ZigFn *exec_fn_entry(Stage1Zir *exec) { - return exec->fn_entry; -} - static Buf *exec_c_import_buf(Stage1Zir *exec) { return exec->c_import_buf; } @@ -3043,7 +3040,7 @@ static IrInstSrc *ir_gen_return(Stage1AstGen *ag, Scope *scope, AstNode *node, L if (expr_node) { // Temporarily set this so that if we return a type it gets the name of the function ZigFn *prev_name_fn = ag->exec->name_fn; - ag->exec->name_fn = exec_fn_entry(ag->exec); + ag->exec->name_fn = ag->fn; return_value = ir_gen_node_extra(ag, expr_node, scope, LValNone, &result_loc_ret->base); ag->exec->name_fn = prev_name_fn; if (return_value == ag->codegen->invalid_inst_src) @@ -4771,8 +4768,9 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdFrameAddress: return ir_lval_wrap(ag, scope, ir_build_frame_address_src(ag, scope, node), lval, result_loc); case BuiltinFnIdFrameHandle: - if (!ag->exec->fn_entry) { - add_node_error(ag->codegen, node, buf_sprintf("@frame() called outside of function definition")); + if (ag->fn == nullptr) { + add_node_error(ag->codegen, node, + buf_sprintf("@frame() called outside of function definition")); return ag->codegen->invalid_inst_src; } return ir_lval_wrap(ag, scope, ir_build_handle_src(ag, scope, node), lval, result_loc); @@ -7700,8 +7698,7 @@ static IrInstSrc *ir_gen_await_expr(Stage1AstGen *ag, Scope *scope, AstNode *nod } } - ZigFn *fn_entry = exec_fn_entry(ag->exec); - if (!fn_entry) { + if (!ag->fn) { add_node_error(ag->codegen, node, buf_sprintf("await outside function definition")); return ag->codegen->invalid_inst_src; } @@ -7726,8 +7723,7 @@ static IrInstSrc *ir_gen_await_expr(Stage1AstGen *ag, Scope *scope, AstNode *nod static IrInstSrc *ir_gen_suspend(Stage1AstGen *ag, Scope *parent_scope, AstNode *node) { assert(node->type == NodeTypeSuspend); - ZigFn *fn_entry = exec_fn_entry(ag->exec); - if (!fn_entry) { + if (!ag->fn) { add_node_error(ag->codegen, node, buf_sprintf("suspend outside function definition")); return ag->codegen->invalid_inst_src; } @@ -8019,7 +8015,7 @@ static IrInstSrc *ir_gen_node_extra(Stage1AstGen *ag, AstNode *node, Scope *scop } Scope *child_scope; if (ag->exec->is_inline || - (ag->exec->fn_entry != nullptr && ag->exec->fn_entry->child_scope == scope)) + (ag->fn != nullptr && ag->fn->child_scope == scope)) { child_scope = scope; } else { @@ -8038,13 +8034,16 @@ static IrInstSrc *ir_gen_node(Stage1AstGen *ag, AstNode *node, Scope *scope) { return ir_gen_node_extra(ag, node, scope, LValNone, nullptr); } -bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, Stage1Zir *ir_executable) { +bool stage1_astgen(CodeGen *codegen, AstNode *node, Scope *scope, Stage1Zir *ir_executable, + ZigFn *fn) +{ assert(node->owner); Stage1AstGen ir_builder = {0}; Stage1AstGen *ag = &ir_builder; ag->codegen = codegen; + ag->fn = fn; ag->exec = ir_executable; ag->main_block_node = node; @@ -8076,15 +8075,10 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, Stage1Zir *ir_executa return true; } -bool ir_gen_fn(CodeGen *codegen, ZigFn *fn_entry) { - assert(fn_entry); - - Stage1Zir *ir_executable = fn_entry->ir_executable; - AstNode *body_node = fn_entry->body_node; - - assert(fn_entry->child_scope); - - return ir_gen(codegen, body_node, fn_entry->child_scope, ir_executable); +bool stage1_astgen_fn(CodeGen *codegen, ZigFn *fn) { + assert(fn != nullptr); + assert(fn->child_scope != nullptr); + return stage1_astgen(codegen, fn->body_node, fn->child_scope, fn->ir_executable, fn); } void invalidate_exec(Stage1Zir *exec, ErrorMsg *msg) { diff --git a/src/stage1/astgen.hpp b/src/stage1/astgen.hpp index 2113637df2..3d22edddef 100644 --- a/src/stage1/astgen.hpp +++ b/src/stage1/astgen.hpp @@ -10,8 +10,8 @@ #include "all_types.hpp" -bool ir_gen(CodeGen *g, AstNode *node, Scope *scope, Stage1Zir *ir_executable); -bool ir_gen_fn(CodeGen *g, ZigFn *fn_entry); +bool stage1_astgen(CodeGen *g, AstNode *node, Scope *scope, Stage1Zir *ir_executable, ZigFn *fn); +bool stage1_astgen_fn(CodeGen *g, ZigFn *fn_entry); bool ir_inst_src_has_side_effects(IrInstSrc *inst); diff --git a/src/stage1/ir.cpp b/src/stage1/ir.cpp index be19e0c8d3..9dac941795 100644 --- a/src/stage1/ir.cpp +++ b/src/stage1/ir.cpp @@ -49,6 +49,7 @@ struct IrAnalyze { Stage1Air *parent_exec; size_t *backward_branch_count; size_t *backward_branch_quota; + ZigFn *fn; // For the purpose of using in a debugger void dump(); @@ -4259,7 +4260,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT continue; } bool allow_infer = cur_type->data.error_set.infer_fn != nullptr && - cur_type->data.error_set.infer_fn == ira->new_irb.exec->fn_entry; + cur_type->data.error_set.infer_fn == ira->fn; if (!allow_infer && !resolve_inferred_error_set(ira->codegen, cur_type, cur_inst->base.source_node)) { return ira->codegen->builtin_types.entry_invalid; } @@ -4327,7 +4328,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT } ZigType *cur_err_set_type = cur_type->data.error_union.err_set_type; bool allow_infer = cur_err_set_type->data.error_set.infer_fn != nullptr && - cur_err_set_type->data.error_set.infer_fn == ira->new_irb.exec->fn_entry; + cur_err_set_type->data.error_set.infer_fn == ira->fn; if (!allow_infer && !resolve_inferred_error_set(ira->codegen, cur_err_set_type, cur_inst->base.source_node)) { return ira->codegen->builtin_types.entry_invalid; } @@ -4382,7 +4383,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT if (cur_type->id == ZigTypeIdErrorSet) { bool allow_infer = cur_type->data.error_set.infer_fn != nullptr && - cur_type->data.error_set.infer_fn == ira->new_irb.exec->fn_entry; + cur_type->data.error_set.infer_fn == ira->fn; if (!allow_infer && !resolve_inferred_error_set(ira->codegen, cur_type, cur_inst->base.source_node)) { return ira->codegen->builtin_types.entry_invalid; } @@ -4401,7 +4402,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT if (prev_type->id == ZigTypeIdErrorUnion) { err_set_type = prev_type->data.error_union.err_set_type; allow_infer = err_set_type->data.error_set.infer_fn != nullptr && - err_set_type->data.error_set.infer_fn == ira->new_irb.exec->fn_entry; + err_set_type->data.error_set.infer_fn == ira->fn; } else { err_set_type = cur_type; } @@ -4465,9 +4466,9 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT continue; bool allow_infer_prev = prev_err_set_type->data.error_set.infer_fn != nullptr && - prev_err_set_type->data.error_set.infer_fn == ira->new_irb.exec->fn_entry; + prev_err_set_type->data.error_set.infer_fn == ira->fn; bool allow_infer_cur = cur_err_set_type->data.error_set.infer_fn != nullptr && - cur_err_set_type->data.error_set.infer_fn == ira->new_irb.exec->fn_entry; + cur_err_set_type->data.error_set.infer_fn == ira->fn; if (!allow_infer_prev && !resolve_inferred_error_set(ira->codegen, prev_err_set_type, cur_inst->base.source_node)) { return ira->codegen->builtin_types.entry_invalid; @@ -4651,7 +4652,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT if (err_set_type != nullptr) { ZigType *cur_err_set_type = cur_type->data.error_union.err_set_type; bool allow_infer = cur_err_set_type->data.error_set.infer_fn != nullptr && - cur_err_set_type->data.error_set.infer_fn == ira->new_irb.exec->fn_entry; + cur_err_set_type->data.error_set.infer_fn == ira->fn; if (!allow_infer && !resolve_inferred_error_set(ira->codegen, cur_err_set_type, cur_inst->base.source_node)) { return ira->codegen->builtin_types.entry_invalid; } @@ -5595,11 +5596,10 @@ Error ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, ir_executable->source_node = source_node; ir_executable->name = exec_name; ir_executable->is_inline = true; - ir_executable->fn_entry = fn_entry; ir_executable->c_import_buf = c_import_buf; ir_executable->begin_scope = scope; - if (!ir_gen(codegen, node, scope, ir_executable)) + if (!stage1_astgen(codegen, node, scope, ir_executable, fn_entry)) return ErrorSemanticAnalyzeFail; if (ir_executable->first_err_trace_msg != nullptr) { @@ -5618,12 +5618,12 @@ Error ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, analyzed_executable->source_exec = ir_executable; analyzed_executable->name = exec_name; analyzed_executable->is_inline = true; - analyzed_executable->fn_entry = fn_entry; analyzed_executable->c_import_buf = c_import_buf; analyzed_executable->begin_scope = scope; ZigType *result_type = ir_analyze(codegen, ir_executable, analyzed_executable, backward_branch_count, backward_branch_quota, - return_ptr->type->data.pointer.child_type, expected_type_source_node, return_ptr); + return_ptr->type->data.pointer.child_type, expected_type_source_node, return_ptr, + fn_entry); if (type_is_invalid(result_type)) { return ErrorSemanticAnalyzeFail; } @@ -11025,7 +11025,7 @@ static IrInstGen *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstSrcDeclV return ira->codegen->invalid_inst_gen; } - ZigFn *fn_entry = ira->new_irb.exec->fn_entry; + ZigFn *fn_entry = ira->fn; if (fn_entry) fn_entry->variable_list.append(var); @@ -11421,9 +11421,9 @@ static IrInstGen *ir_analyze_instruction_extern(IrAnalyze *ira, IrInstSrcExtern is_thread_local, expr_type); } -static bool exec_has_err_ret_trace(CodeGen *g, Stage1Zir *exec) { - ZigFn *fn_entry = exec->fn_entry; - return fn_entry != nullptr && fn_entry->calls_or_awaits_errorable_fn && g->have_err_ret_tracing; +static bool ira_has_err_ret_trace(IrAnalyze *ira) { + ZigFn *fn = ira->fn; + return fn != nullptr && fn->calls_or_awaits_errorable_fn && ira->codegen->have_err_ret_tracing; } static IrInstGen *ir_analyze_instruction_error_return_trace(IrAnalyze *ira, @@ -11432,7 +11432,7 @@ static IrInstGen *ir_analyze_instruction_error_return_trace(IrAnalyze *ira, ZigType *ptr_to_stack_trace_type = get_pointer_to_type(ira->codegen, get_stack_trace_type(ira->codegen), false); if (instruction->optional == IrInstErrorReturnTraceNull) { ZigType *optional_type = get_optional_type(ira->codegen, ptr_to_stack_trace_type); - if (!exec_has_err_ret_trace(ira->codegen, ira->zir)) { + if (!ira_has_err_ret_trace(ira)) { IrInstGen *result = ir_const(ira, &instruction->base.base, optional_type); ZigValue *out_val = result->value; assert(get_src_ptr_type(optional_type) != nullptr); @@ -11504,7 +11504,7 @@ static IrInstGen *ir_analyze_alloca(IrAnalyze *ira, IrInst *source_inst, ZigType PtrLenSingle, align, 0, 0, false); if (!force_comptime) { - ZigFn *fn_entry = ira->new_irb.exec->fn_entry; + ZigFn *fn_entry = ira->fn; if (fn_entry != nullptr) { fn_entry->alloca_gen_list.append(result); } @@ -11603,7 +11603,7 @@ static IrInstGen *ir_resolve_no_result_loc(IrAnalyze *ira, IrInst *suspend_sourc alloca_gen->base.value->type = get_pointer_to_type_extra(ira->codegen, value_type, false, false, PtrLenSingle, 0, 0, 0, false); set_up_result_loc_for_inferred_comptime(ira, &alloca_gen->base); - ZigFn *fn_entry = ira->new_irb.exec->fn_entry; + ZigFn *fn_entry = ira->fn; if (fn_entry != nullptr && get_scope_typeof(suspend_source_instr->scope) == nullptr) { fn_entry->alloca_gen_list.append(alloca_gen); } @@ -12131,7 +12131,7 @@ static IrInstGen *ir_analyze_instruction_resolve_result(IrAnalyze *ira, IrInstSr if (result_loc != nullptr) return result_loc; - ZigFn *fn = ira->new_irb.exec->fn_entry; + ZigFn *fn = ira->fn; if (fn != nullptr && fn->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync && instruction->result_loc->id == ResultLocIdReturn) { @@ -12849,7 +12849,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, } } - ZigFn *parent_fn_entry = ira->new_irb.exec->fn_entry; + ZigFn *parent_fn_entry = ira->fn; assert(parent_fn_entry); for (size_t call_i = 0; call_i < args_len; call_i += 1) { IrInstGen *arg = args_ptr[call_i]; @@ -13017,7 +13017,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, return ir_finish_anal(ira, &new_call_instruction->base); } - ZigFn *parent_fn_entry = ira->new_irb.exec->fn_entry; + ZigFn *parent_fn_entry = ira->fn; assert(fn_type_id->return_type != nullptr); assert(parent_fn_entry != nullptr); if (fn_type_can_fail(fn_type_id)) { @@ -21069,7 +21069,7 @@ static IrInstGen *ir_analyze_instruction_frame_address(IrAnalyze *ira, IrInstSrc } static IrInstGen *ir_analyze_instruction_frame_handle(IrAnalyze *ira, IrInstSrcFrameHandle *instruction) { - ZigFn *fn = ira->new_irb.exec->fn_entry; + ZigFn *fn = ira->fn; ir_assert(fn != nullptr, &instruction->base.base); if (fn->inferred_async_node == nullptr) { @@ -22932,7 +22932,7 @@ static IrInstGen *ir_analyze_instruction_set_align_stack(IrAnalyze *ira, IrInstS return ira->codegen->invalid_inst_gen; } - ZigFn *fn_entry = ira->new_irb.exec->fn_entry; + ZigFn *fn_entry = ira->fn; if (fn_entry == nullptr) { ir_add_error(ira, &instruction->base.base, buf_sprintf("@setAlignStack outside function")); return ira->codegen->invalid_inst_gen; @@ -23952,7 +23952,7 @@ static IrInstGen *ir_analyze_instruction_suspend_finish(IrAnalyze *ira, IrInstSr ir_assert(begin_base->id == IrInstGenIdSuspendBegin, &instruction->base.base); IrInstGenSuspendBegin *begin = reinterpret_cast(begin_base); - ZigFn *fn_entry = ira->new_irb.exec->fn_entry; + ZigFn *fn_entry = ira->fn; ir_assert(fn_entry != nullptr, &instruction->base.base); if (fn_entry->inferred_async_node == nullptr) { @@ -24019,7 +24019,7 @@ static IrInstGen *ir_analyze_instruction_await(IrAnalyze *ira, IrInstSrcAwait *i ZigType *result_type = frame->value->type->data.any_frame.result_type; - ZigFn *fn_entry = ira->new_irb.exec->fn_entry; + ZigFn *fn_entry = ira->fn; ir_assert(fn_entry != nullptr, &instruction->base.base); // If it's not @Frame(func) then it's definitely a suspend point @@ -24465,16 +24465,17 @@ static IrInstGen *ir_analyze_instruction_base(IrAnalyze *ira, IrInstSrc *instruc zig_unreachable(); } -// This function attempts to evaluate IR code while doing type checking and other analysis. +// This function attempts to evaluate stage1 ZIR code while doing type checking and other analysis. // It emits to a new Stage1Air which is partially evaluated IR code. ZigType *ir_analyze(CodeGen *codegen, Stage1Zir *stage1_zir, Stage1Air *stage1_air, size_t *backward_branch_count, size_t *backward_branch_quota, - ZigType *expected_type, AstNode *expected_type_source_node, ZigValue *result_ptr) + ZigType *expected_type, AstNode *expected_type_source_node, ZigValue *result_ptr, ZigFn *fn) { assert(stage1_zir->first_err_trace_msg == nullptr); assert(expected_type == nullptr || !type_is_invalid(expected_type)); IrAnalyze *ira = heap::c_allocator.create(); + ira->fn = fn; ira->backward_branch_count = backward_branch_count; ira->backward_branch_quota = backward_branch_quota; ira->ref_count = 1; diff --git a/src/stage1/ir.hpp b/src/stage1/ir.hpp index eece7e298f..504802aafb 100644 --- a/src/stage1/ir.hpp +++ b/src/stage1/ir.hpp @@ -22,10 +22,10 @@ Error ir_resolve_lazy(CodeGen *codegen, AstNode *source_node, ZigValue *val); ZigType *ir_analyze(CodeGen *codegen, Stage1Zir *stage1_zir, Stage1Air *stage1_air, size_t *backward_branch_count, size_t *backward_branch_quota, - ZigType *expected_type, AstNode *expected_type_source_node, ZigValue *result_ptr); + ZigType *expected_type, AstNode *expected_type_source_node, ZigValue *result_ptr, + ZigFn *fn); bool ir_inst_gen_has_side_effects(IrInstGen *inst); -bool ir_inst_src_has_side_effects(IrInstSrc *inst); struct IrAnalyze; ZigValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ZigValue *const_val, diff --git a/src/stage1/ir_print.cpp b/src/stage1/ir_print.cpp index 1fdf0e14d5..c9b80b8675 100644 --- a/src/stage1/ir_print.cpp +++ b/src/stage1/ir_print.cpp @@ -8,6 +8,7 @@ #include "all_types.hpp" #include "analyze.hpp" #include "ir.hpp" +#include "astgen.hpp" #include "ir_print.hpp" #include "os.hpp" From 554dd52c36711e9b07f35e20c3427027ad2fa60f Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 27 May 2021 21:07:20 -0700 Subject: [PATCH 08/14] stage1: remove c_import_buf from Stage1Zir All we need is a boolean in Stage1AstGen. This is part of an effort to make Stage1Zir immutable. --- src/stage1/all_types.hpp | 1 - src/stage1/astgen.cpp | 16 +++++++--------- src/stage1/astgen.hpp | 3 ++- src/stage1/ir.cpp | 5 +++-- 4 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/stage1/all_types.hpp b/src/stage1/all_types.hpp index 249ca34b1f..3ece851e41 100644 --- a/src/stage1/all_types.hpp +++ b/src/stage1/all_types.hpp @@ -114,7 +114,6 @@ struct Stage1Zir { ZigList basic_block_list; Buf *name; ZigFn *name_fn; - Buf *c_import_buf; AstNode *source_node; Scope *begin_scope; ErrorMsg *first_err_trace_msg; diff --git a/src/stage1/astgen.cpp b/src/stage1/astgen.cpp index a82f156cda..2739c04687 100644 --- a/src/stage1/astgen.cpp +++ b/src/stage1/astgen.cpp @@ -18,6 +18,7 @@ struct Stage1AstGen { AstNode *main_block_node; size_t next_debug_id; ZigFn *fn; + bool in_c_import_scope; }; static IrInstSrc *ir_gen_node(Stage1AstGen *ag, AstNode *node, Scope *scope); @@ -369,10 +370,6 @@ static size_t irb_next_debug_id(Stage1AstGen *ag) { return result; } -static Buf *exec_c_import_buf(Stage1Zir *exec) { - return exec->c_import_buf; -} - static void ir_ref_bb(IrBasicBlockSrc *bb) { bb->ref_count += 1; } @@ -4215,7 +4212,7 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; - if (!exec_c_import_buf(ag->exec)) { + if (!ag->in_c_import_scope) { add_node_error(ag->codegen, node, buf_sprintf("C include valid only inside C import block")); return ag->codegen->invalid_inst_src; } @@ -4235,7 +4232,7 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; - if (!exec_c_import_buf(ag->exec)) { + if (!ag->in_c_import_scope) { add_node_error(ag->codegen, node, buf_sprintf("C define valid only inside C import block")); return ag->codegen->invalid_inst_src; } @@ -4250,7 +4247,7 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; - if (!exec_c_import_buf(ag->exec)) { + if (!ag->in_c_import_scope) { add_node_error(ag->codegen, node, buf_sprintf("C undef valid only inside C import block")); return ag->codegen->invalid_inst_src; } @@ -8035,7 +8032,7 @@ static IrInstSrc *ir_gen_node(Stage1AstGen *ag, AstNode *node, Scope *scope) { } bool stage1_astgen(CodeGen *codegen, AstNode *node, Scope *scope, Stage1Zir *ir_executable, - ZigFn *fn) + ZigFn *fn, bool in_c_import_scope) { assert(node->owner); @@ -8044,6 +8041,7 @@ bool stage1_astgen(CodeGen *codegen, AstNode *node, Scope *scope, Stage1Zir *ir_ ag->codegen = codegen; ag->fn = fn; + ag->in_c_import_scope = in_c_import_scope; ag->exec = ir_executable; ag->main_block_node = node; @@ -8078,7 +8076,7 @@ bool stage1_astgen(CodeGen *codegen, AstNode *node, Scope *scope, Stage1Zir *ir_ bool stage1_astgen_fn(CodeGen *codegen, ZigFn *fn) { assert(fn != nullptr); assert(fn->child_scope != nullptr); - return stage1_astgen(codegen, fn->body_node, fn->child_scope, fn->ir_executable, fn); + return stage1_astgen(codegen, fn->body_node, fn->child_scope, fn->ir_executable, fn, false); } void invalidate_exec(Stage1Zir *exec, ErrorMsg *msg) { diff --git a/src/stage1/astgen.hpp b/src/stage1/astgen.hpp index 3d22edddef..ffdc1d08bf 100644 --- a/src/stage1/astgen.hpp +++ b/src/stage1/astgen.hpp @@ -10,7 +10,8 @@ #include "all_types.hpp" -bool stage1_astgen(CodeGen *g, AstNode *node, Scope *scope, Stage1Zir *ir_executable, ZigFn *fn); +bool stage1_astgen(CodeGen *g, AstNode *node, Scope *scope, Stage1Zir *ir_executable, + ZigFn *fn, bool in_c_import_scope); bool stage1_astgen_fn(CodeGen *g, ZigFn *fn_entry); bool ir_inst_src_has_side_effects(IrInstSrc *inst); diff --git a/src/stage1/ir.cpp b/src/stage1/ir.cpp index 9dac941795..5cae9a9a4f 100644 --- a/src/stage1/ir.cpp +++ b/src/stage1/ir.cpp @@ -5596,10 +5596,11 @@ Error ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, ir_executable->source_node = source_node; ir_executable->name = exec_name; ir_executable->is_inline = true; - ir_executable->c_import_buf = c_import_buf; ir_executable->begin_scope = scope; - if (!stage1_astgen(codegen, node, scope, ir_executable, fn_entry)) + bool in_c_import_scope = c_import_buf != nullptr; + + if (!stage1_astgen(codegen, node, scope, ir_executable, fn_entry, in_c_import_scope)) return ErrorSemanticAnalyzeFail; if (ir_executable->first_err_trace_msg != nullptr) { From 548ef780707eb2b438015c28d594a59a3f37ba3e Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 27 May 2021 21:23:20 -0700 Subject: [PATCH 09/14] stage1: remove source_node field from Stage1Zir This field is unneeded because we always have the source node available in the context that we have a Stage1Zir object. --- src/stage1/all_types.hpp | 7 +------ src/stage1/analyze.cpp | 14 ++++---------- src/stage1/astgen.cpp | 6 +++--- src/stage1/astgen.hpp | 2 +- src/stage1/ir.cpp | 22 ++++++++++------------ 5 files changed, 19 insertions(+), 32 deletions(-) diff --git a/src/stage1/all_types.hpp b/src/stage1/all_types.hpp index 3ece851e41..ab8ed16292 100644 --- a/src/stage1/all_types.hpp +++ b/src/stage1/all_types.hpp @@ -114,17 +114,12 @@ struct Stage1Zir { ZigList basic_block_list; Buf *name; ZigFn *name_fn; - AstNode *source_node; Scope *begin_scope; ErrorMsg *first_err_trace_msg; ZigList tld_list; bool is_inline; bool need_err_code_spill; - - // This is a function for use in the debugger to print - // the source location. - void src(); }; struct Stage1Air { @@ -1638,7 +1633,7 @@ struct ZigFn { // in the case of async functions this is the implicit return type according to the // zig source code, not according to zig ir ZigType *src_implicit_return_type; - Stage1Zir *ir_executable; + Stage1Zir *stage1_zir; Stage1Air analyzed_executable; size_t branch_quota; AstNode **param_source_nodes; diff --git a/src/stage1/analyze.cpp b/src/stage1/analyze.cpp index 64ad75a2ad..0eef78b1f4 100644 --- a/src/stage1/analyze.cpp +++ b/src/stage1/analyze.cpp @@ -3653,7 +3653,7 @@ static void get_fully_qualified_decl_name(CodeGen *g, Buf *buf, Tld *tld, bool i static ZigFn *create_fn_raw(CodeGen *g, bool is_noinline) { ZigFn *fn_entry = heap::c_allocator.create(); - fn_entry->ir_executable = heap::c_allocator.create(); + fn_entry->stage1_zir = heap::c_allocator.create(); fn_entry->is_noinline = is_noinline; return fn_entry; @@ -5129,7 +5129,7 @@ static void analyze_fn_ir(CodeGen *g, ZigFn *fn, AstNode *return_type_node) { } size_t backward_branch_count = 0; size_t backward_branch_quota = max(fn->branch_quota, default_backward_branch_quota); - ZigType *block_return_type = ir_analyze(g, fn->ir_executable, &fn->analyzed_executable, + ZigType *block_return_type = ir_analyze(g, fn->stage1_zir, &fn->analyzed_executable, &backward_branch_count, &backward_branch_quota, fn_type_id->return_type, return_type_node, nullptr, fn); fn->src_implicit_return_type = block_return_type; @@ -5233,14 +5233,14 @@ static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry) { return; } - if (fn_table_entry->ir_executable->first_err_trace_msg != nullptr) { + if (fn_table_entry->stage1_zir->first_err_trace_msg != nullptr) { fn_table_entry->anal_state = FnAnalStateInvalid; return; } if (g->verbose_ir) { fprintf(stderr, "\nfn %s() { // (IR)\n", buf_ptr(&fn_table_entry->symbol_name)); - ir_print_src(g, stderr, fn_table_entry->ir_executable, 4); + ir_print_src(g, stderr, fn_table_entry->stage1_zir, 4); fprintf(stderr, "}\n"); } @@ -9858,12 +9858,6 @@ void AstNode::src() { line, column); } -void Stage1Zir::src() { - if (this->source_node != nullptr) { - this->source_node->src(); - } -} - void Stage1Air::src() { Stage1Air *it; for (it = this; it != nullptr && it->source_node != nullptr; it = it->parent_exec) { diff --git a/src/stage1/astgen.cpp b/src/stage1/astgen.cpp index 2739c04687..fe0da3c5ce 100644 --- a/src/stage1/astgen.cpp +++ b/src/stage1/astgen.cpp @@ -8031,7 +8031,7 @@ static IrInstSrc *ir_gen_node(Stage1AstGen *ag, AstNode *node, Scope *scope) { return ir_gen_node_extra(ag, node, scope, LValNone, nullptr); } -bool stage1_astgen(CodeGen *codegen, AstNode *node, Scope *scope, Stage1Zir *ir_executable, +bool stage1_astgen(CodeGen *codegen, AstNode *node, Scope *scope, Stage1Zir *stage1_zir, ZigFn *fn, bool in_c_import_scope) { assert(node->owner); @@ -8042,7 +8042,7 @@ bool stage1_astgen(CodeGen *codegen, AstNode *node, Scope *scope, Stage1Zir *ir_ ag->codegen = codegen; ag->fn = fn; ag->in_c_import_scope = in_c_import_scope; - ag->exec = ir_executable; + ag->exec = stage1_zir; ag->main_block_node = node; IrBasicBlockSrc *entry_block = ir_create_basic_block(ag, scope, "Entry"); @@ -8076,7 +8076,7 @@ bool stage1_astgen(CodeGen *codegen, AstNode *node, Scope *scope, Stage1Zir *ir_ bool stage1_astgen_fn(CodeGen *codegen, ZigFn *fn) { assert(fn != nullptr); assert(fn->child_scope != nullptr); - return stage1_astgen(codegen, fn->body_node, fn->child_scope, fn->ir_executable, fn, false); + return stage1_astgen(codegen, fn->body_node, fn->child_scope, fn->stage1_zir, fn, false); } void invalidate_exec(Stage1Zir *exec, ErrorMsg *msg) { diff --git a/src/stage1/astgen.hpp b/src/stage1/astgen.hpp index ffdc1d08bf..eb93fd5b73 100644 --- a/src/stage1/astgen.hpp +++ b/src/stage1/astgen.hpp @@ -10,7 +10,7 @@ #include "all_types.hpp" -bool stage1_astgen(CodeGen *g, AstNode *node, Scope *scope, Stage1Zir *ir_executable, +bool stage1_astgen(CodeGen *g, AstNode *node, Scope *scope, Stage1Zir *stage1_zir, ZigFn *fn, bool in_c_import_scope); bool stage1_astgen_fn(CodeGen *g, ZigFn *fn_entry); diff --git a/src/stage1/ir.cpp b/src/stage1/ir.cpp index 5cae9a9a4f..9188c746da 100644 --- a/src/stage1/ir.cpp +++ b/src/stage1/ir.cpp @@ -5592,36 +5592,35 @@ Error ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, if (type_is_invalid(return_ptr->type)) return ErrorSemanticAnalyzeFail; - Stage1Zir *ir_executable = heap::c_allocator.create(); - ir_executable->source_node = source_node; - ir_executable->name = exec_name; - ir_executable->is_inline = true; - ir_executable->begin_scope = scope; + Stage1Zir *stage1_zir = heap::c_allocator.create(); + stage1_zir->name = exec_name; + stage1_zir->is_inline = true; + stage1_zir->begin_scope = scope; bool in_c_import_scope = c_import_buf != nullptr; - if (!stage1_astgen(codegen, node, scope, ir_executable, fn_entry, in_c_import_scope)) + if (!stage1_astgen(codegen, node, scope, stage1_zir, fn_entry, in_c_import_scope)) return ErrorSemanticAnalyzeFail; - if (ir_executable->first_err_trace_msg != nullptr) { - codegen->trace_err = ir_executable->first_err_trace_msg; + if (stage1_zir->first_err_trace_msg != nullptr) { + codegen->trace_err = stage1_zir->first_err_trace_msg; return ErrorSemanticAnalyzeFail; } if (codegen->verbose_ir) { fprintf(stderr, "\n{ // (IR)\n"); - ir_print_src(codegen, stderr, ir_executable, 2); + ir_print_src(codegen, stderr, stage1_zir, 2); fprintf(stderr, "}\n"); } Stage1Air *analyzed_executable = heap::c_allocator.create(); analyzed_executable->source_node = source_node; analyzed_executable->parent_exec = parent_exec; - analyzed_executable->source_exec = ir_executable; + analyzed_executable->source_exec = stage1_zir; analyzed_executable->name = exec_name; analyzed_executable->is_inline = true; analyzed_executable->c_import_buf = c_import_buf; analyzed_executable->begin_scope = scope; - ZigType *result_type = ir_analyze(codegen, ir_executable, analyzed_executable, + ZigType *result_type = ir_analyze(codegen, stage1_zir, analyzed_executable, backward_branch_count, backward_branch_quota, return_ptr->type->data.pointer.child_type, expected_type_source_node, return_ptr, fn_entry); @@ -12935,7 +12934,6 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, if (type_is_invalid(impl_fn->type_entry)) return ira->codegen->invalid_inst_gen; - impl_fn->ir_executable->source_node = source_instr->source_node; impl_fn->analyzed_executable.source_node = source_instr->source_node; impl_fn->analyzed_executable.parent_exec = ira->new_irb.exec; impl_fn->branch_quota = *ira->backward_branch_quota; From 01e0a4b2f06d60a58b3d2df410776b164d05c1ec Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 27 May 2021 21:27:06 -0700 Subject: [PATCH 10/14] stage1: rename IrBasicBlockSrc to Stage1ZirBasicBlock --- src/stage1/all_types.hpp | 34 +++---- src/stage1/astgen.cpp | 192 +++++++++++++++++++-------------------- src/stage1/ir.cpp | 36 ++++---- src/stage1/ir_print.cpp | 8 +- src/stage1/ir_print.hpp | 2 +- 5 files changed, 136 insertions(+), 136 deletions(-) diff --git a/src/stage1/all_types.hpp b/src/stage1/all_types.hpp index ab8ed16292..3af41c5788 100644 --- a/src/stage1/all_types.hpp +++ b/src/stage1/all_types.hpp @@ -38,7 +38,7 @@ struct IrInstGenCast; struct IrInstGenAlloca; struct IrInstGenCall; struct IrInstGenAwait; -struct IrBasicBlockSrc; +struct Stage1ZirBasicBlock; struct IrBasicBlockGen; struct ScopeDecls; struct ZigWindowsSDK; @@ -111,7 +111,7 @@ enum X64CABIClass { }; struct Stage1Zir { - ZigList basic_block_list; + ZigList basic_block_list; Buf *name; ZigFn *name_fn; Scope *begin_scope; @@ -2255,11 +2255,11 @@ struct ScopeBlock { Scope base; Buf *name; - IrBasicBlockSrc *end_block; + Stage1ZirBasicBlock *end_block; IrInstSrc *is_comptime; ResultLocPeerParent *peer_parent; ZigList *incoming_values; - ZigList *incoming_blocks; + ZigList *incoming_blocks; AstNode *safety_set_node; AstNode *fast_math_set_node; @@ -2311,11 +2311,11 @@ struct ScopeLoop { LVal lval; Buf *name; - IrBasicBlockSrc *break_block; - IrBasicBlockSrc *continue_block; + Stage1ZirBasicBlock *break_block; + Stage1ZirBasicBlock *continue_block; IrInstSrc *is_comptime; ZigList *incoming_values; - ZigList *incoming_blocks; + ZigList *incoming_blocks; ResultLocPeerParent *peer_parent; ScopeExpr *spill_scope; @@ -2426,7 +2426,7 @@ enum AtomicRmwOp { // to another basic block. // Phi instructions must be first in a basic block. // The last instruction in a basic block must be of type unreachable. -struct IrBasicBlockSrc { +struct Stage1ZirBasicBlock { ZigList instruction_list; IrBasicBlockGen *child; Scope *scope; @@ -2729,7 +2729,7 @@ struct IrInstSrc { // can find the instruction that corresponds to this value in the "new ir" // with this child field. IrInstGen *child; - IrBasicBlockSrc *owner_bb; + Stage1ZirBasicBlock *owner_bb; // for debugging purposes, these are useful to call to inspect the instruction void dump(); @@ -2774,8 +2774,8 @@ struct IrInstSrcCondBr { IrInstSrc base; IrInstSrc *condition; - IrBasicBlockSrc *then_block; - IrBasicBlockSrc *else_block; + Stage1ZirBasicBlock *then_block; + Stage1ZirBasicBlock *else_block; IrInstSrc *is_comptime; ResultLoc *result_loc; }; @@ -2791,7 +2791,7 @@ struct IrInstGenCondBr { struct IrInstSrcBr { IrInstSrc base; - IrBasicBlockSrc *dest_block; + Stage1ZirBasicBlock *dest_block; IrInstSrc *is_comptime; }; @@ -2803,14 +2803,14 @@ struct IrInstGenBr { struct IrInstSrcSwitchBrCase { IrInstSrc *value; - IrBasicBlockSrc *block; + Stage1ZirBasicBlock *block; }; struct IrInstSrcSwitchBr { IrInstSrc base; IrInstSrc *target_value; - IrBasicBlockSrc *else_block; + Stage1ZirBasicBlock *else_block; size_t case_count; IrInstSrcSwitchBrCase *cases; IrInstSrc *is_comptime; @@ -2856,7 +2856,7 @@ struct IrInstSrcPhi { IrInstSrc base; size_t incoming_count; - IrBasicBlockSrc **incoming_blocks; + Stage1ZirBasicBlock **incoming_blocks; IrInstSrc **incoming_values; ResultLocPeerParent *peer_parent; }; @@ -4520,7 +4520,7 @@ struct ResultLocPeerParent { bool skipped; bool done_resuming; - IrBasicBlockSrc *end_bb; + Stage1ZirBasicBlock *end_bb; ResultLoc *parent; ZigList peers; ZigType *resolved_type; @@ -4531,7 +4531,7 @@ struct ResultLocPeer { ResultLoc base; ResultLocPeerParent *parent; - IrBasicBlockSrc *next_bb; + Stage1ZirBasicBlock *next_bb; IrSuspendPosition suspend_pos; }; diff --git a/src/stage1/astgen.cpp b/src/stage1/astgen.cpp index fe0da3c5ce..d7ec91f466 100644 --- a/src/stage1/astgen.cpp +++ b/src/stage1/astgen.cpp @@ -14,7 +14,7 @@ struct Stage1AstGen { CodeGen *codegen; Stage1Zir *exec; - IrBasicBlockSrc *current_basic_block; + Stage1ZirBasicBlock *current_basic_block; AstNode *main_block_node; size_t next_debug_id; ZigFn *fn; @@ -358,7 +358,7 @@ bool ir_should_inline(Stage1Zir *exec, Scope *scope) { return false; } -static void ir_instruction_append(IrBasicBlockSrc *basic_block, IrInstSrc *instruction) { +static void ir_instruction_append(Stage1ZirBasicBlock *basic_block, IrInstSrc *instruction) { assert(basic_block); assert(instruction); basic_block->instruction_list.append(instruction); @@ -370,11 +370,11 @@ static size_t irb_next_debug_id(Stage1AstGen *ag) { return result; } -static void ir_ref_bb(IrBasicBlockSrc *bb) { +static void ir_ref_bb(Stage1ZirBasicBlock *bb) { bb->ref_count += 1; } -static void ir_ref_instruction(IrInstSrc *instruction, IrBasicBlockSrc *cur_bb) { +static void ir_ref_instruction(IrInstSrc *instruction, Stage1ZirBasicBlock *cur_bb) { assert(instruction->id != IrInstSrcIdInvalid); instruction->base.ref_count += 1; if (instruction->owner_bb != cur_bb && !instr_is_unreachable(instruction) @@ -384,8 +384,8 @@ static void ir_ref_instruction(IrInstSrc *instruction, IrBasicBlockSrc *cur_bb) } } -static IrBasicBlockSrc *ir_create_basic_block(Stage1AstGen *ag, Scope *scope, const char *name_hint) { - IrBasicBlockSrc *result = heap::c_allocator.create(); +static Stage1ZirBasicBlock *ir_create_basic_block(Stage1AstGen *ag, Scope *scope, const char *name_hint) { + Stage1ZirBasicBlock *result = heap::c_allocator.create(); result->scope = scope; result->name_hint = name_hint; result->debug_id = irb_next_debug_id(ag); @@ -944,7 +944,7 @@ static T *ir_build_instruction(Stage1AstGen *ag, Scope *scope, AstNode *source_n } static IrInstSrc *ir_build_cond_br(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *condition, - IrBasicBlockSrc *then_block, IrBasicBlockSrc *else_block, IrInstSrc *is_comptime) + Stage1ZirBasicBlock *then_block, Stage1ZirBasicBlock *else_block, IrInstSrc *is_comptime) { IrInstSrcCondBr *inst = ir_build_instruction(ag, scope, source_node); inst->base.is_noreturn = true; @@ -1279,7 +1279,7 @@ static IrInstSrc *ir_build_call_src(Stage1AstGen *ag, Scope *scope, AstNode *sou } static IrInstSrc *ir_build_phi(Stage1AstGen *ag, Scope *scope, AstNode *source_node, - size_t incoming_count, IrBasicBlockSrc **incoming_blocks, IrInstSrc **incoming_values, + size_t incoming_count, Stage1ZirBasicBlock **incoming_blocks, IrInstSrc **incoming_values, ResultLocPeerParent *peer_parent) { assert(incoming_count != 0); @@ -1300,7 +1300,7 @@ static IrInstSrc *ir_build_phi(Stage1AstGen *ag, Scope *scope, AstNode *source_n } static IrInstSrc *ir_build_br(Stage1AstGen *ag, Scope *scope, AstNode *source_node, - IrBasicBlockSrc *dest_block, IrInstSrc *is_comptime) + Stage1ZirBasicBlock *dest_block, IrInstSrc *is_comptime) { IrInstSrcBr *inst = ir_build_instruction(ag, scope, source_node); inst->base.is_noreturn = true; @@ -1714,7 +1714,7 @@ static IrInstSrc *ir_build_bit_reverse(Stage1AstGen *ag, Scope *scope, AstNode * } static IrInstSrcSwitchBr *ir_build_switch_br_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, - IrInstSrc *target_value, IrBasicBlockSrc *else_block, size_t case_count, IrInstSrcSwitchBrCase *cases, + IrInstSrc *target_value, Stage1ZirBasicBlock *else_block, size_t case_count, IrInstSrcSwitchBrCase *cases, IrInstSrc *is_comptime, IrInstSrc *switch_prongs_void) { IrInstSrcSwitchBr *instruction = ir_build_instruction(ag, scope, source_node); @@ -2976,12 +2976,12 @@ static bool ir_gen_defers_for_block(Stage1AstGen *ag, Scope *inner_scope, Scope return true; } -static void ir_set_cursor_at_end(Stage1AstGen *ag, IrBasicBlockSrc *basic_block) { +static void ir_set_cursor_at_end(Stage1AstGen *ag, Stage1ZirBasicBlock *basic_block) { assert(basic_block); ag->current_basic_block = basic_block; } -static void ir_set_cursor_at_end_and_append_block(Stage1AstGen *ag, IrBasicBlockSrc *basic_block) { +static void ir_set_cursor_at_end_and_append_block(Stage1AstGen *ag, Stage1ZirBasicBlock *basic_block) { basic_block->index = ag->exec->basic_block_list.length; ag->exec->basic_block_list.append(basic_block); ir_set_cursor_at_end(ag, basic_block); @@ -3062,8 +3062,8 @@ static IrInstSrc *ir_gen_return(Stage1AstGen *ag, Scope *scope, AstNode *node, L } bool should_inline = ir_should_inline(ag->exec, scope); - IrBasicBlockSrc *err_block = ir_create_basic_block(ag, scope, "ErrRetErr"); - IrBasicBlockSrc *ok_block = ir_create_basic_block(ag, scope, "ErrRetOk"); + Stage1ZirBasicBlock *err_block = ir_create_basic_block(ag, scope, "ErrRetErr"); + Stage1ZirBasicBlock *ok_block = ir_create_basic_block(ag, scope, "ErrRetOk"); IrInstSrc *is_err = ir_build_test_err_src(ag, scope, node, return_value, false, true); @@ -3075,7 +3075,7 @@ static IrInstSrc *ir_gen_return(Stage1AstGen *ag, Scope *scope, AstNode *node, L } ir_mark_gen(ir_build_cond_br(ag, scope, node, is_err, err_block, ok_block, is_comptime)); - IrBasicBlockSrc *ret_stmt_block = ir_create_basic_block(ag, scope, "RetStmt"); + Stage1ZirBasicBlock *ret_stmt_block = ir_create_basic_block(ag, scope, "RetStmt"); ir_set_cursor_at_end_and_append_block(ag, err_block); if (!ir_gen_defers_for_block(ag, scope, outer_scope, nullptr, return_value)) @@ -3103,8 +3103,8 @@ static IrInstSrc *ir_gen_return(Stage1AstGen *ag, Scope *scope, AstNode *node, L return ag->codegen->invalid_inst_src; IrInstSrc *is_err_val = ir_build_test_err_src(ag, scope, node, err_union_ptr, true, false); - IrBasicBlockSrc *return_block = ir_create_basic_block(ag, scope, "ErrRetReturn"); - IrBasicBlockSrc *continue_block = ir_create_basic_block(ag, scope, "ErrRetContinue"); + Stage1ZirBasicBlock *return_block = ir_create_basic_block(ag, scope, "ErrRetReturn"); + Stage1ZirBasicBlock *continue_block = ir_create_basic_block(ag, scope, "ErrRetContinue"); IrInstSrc *is_comptime; bool should_inline = ir_should_inline(ag->exec, scope); if (should_inline) { @@ -3266,7 +3266,7 @@ static IrInstSrc *ir_gen_block(Stage1AstGen *ag, Scope *parent_scope, AstNode *b assert(block_node->type == NodeTypeBlock); ZigList incoming_values = {0}; - ZigList incoming_blocks = {0}; + ZigList incoming_blocks = {0}; if (is_duplicate_label(ag->codegen, parent_scope, block_node, block_node->data.block.name)) return ag->codegen->invalid_inst_src; @@ -3479,7 +3479,7 @@ static IrInstSrc *ir_gen_bool_or(Stage1AstGen *ag, Scope *scope, AstNode *node) IrInstSrc *val1 = ir_gen_node(ag, node->data.bin_op_expr.op1, scope); if (val1 == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; - IrBasicBlockSrc *post_val1_block = ag->current_basic_block; + Stage1ZirBasicBlock *post_val1_block = ag->current_basic_block; IrInstSrc *is_comptime; if (ir_should_inline(ag->exec, scope)) { @@ -3489,9 +3489,9 @@ static IrInstSrc *ir_gen_bool_or(Stage1AstGen *ag, Scope *scope, AstNode *node) } // block for when val1 == false - IrBasicBlockSrc *false_block = ir_create_basic_block(ag, scope, "BoolOrFalse"); + Stage1ZirBasicBlock *false_block = ir_create_basic_block(ag, scope, "BoolOrFalse"); // block for when val1 == true (don't even evaluate the second part) - IrBasicBlockSrc *true_block = ir_create_basic_block(ag, scope, "BoolOrTrue"); + Stage1ZirBasicBlock *true_block = ir_create_basic_block(ag, scope, "BoolOrTrue"); ir_build_cond_br(ag, scope, node, val1, true_block, false_block, is_comptime); @@ -3499,7 +3499,7 @@ static IrInstSrc *ir_gen_bool_or(Stage1AstGen *ag, Scope *scope, AstNode *node) IrInstSrc *val2 = ir_gen_node(ag, node->data.bin_op_expr.op2, scope); if (val2 == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; - IrBasicBlockSrc *post_val2_block = ag->current_basic_block; + Stage1ZirBasicBlock *post_val2_block = ag->current_basic_block; ir_build_br(ag, scope, node, true_block, is_comptime); @@ -3508,7 +3508,7 @@ static IrInstSrc *ir_gen_bool_or(Stage1AstGen *ag, Scope *scope, AstNode *node) IrInstSrc **incoming_values = heap::c_allocator.allocate(2); incoming_values[0] = val1; incoming_values[1] = val2; - IrBasicBlockSrc **incoming_blocks = heap::c_allocator.allocate(2); + Stage1ZirBasicBlock **incoming_blocks = heap::c_allocator.allocate(2); incoming_blocks[0] = post_val1_block; incoming_blocks[1] = post_val2_block; @@ -3521,7 +3521,7 @@ static IrInstSrc *ir_gen_bool_and(Stage1AstGen *ag, Scope *scope, AstNode *node) IrInstSrc *val1 = ir_gen_node(ag, node->data.bin_op_expr.op1, scope); if (val1 == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; - IrBasicBlockSrc *post_val1_block = ag->current_basic_block; + Stage1ZirBasicBlock *post_val1_block = ag->current_basic_block; IrInstSrc *is_comptime; if (ir_should_inline(ag->exec, scope)) { @@ -3531,9 +3531,9 @@ static IrInstSrc *ir_gen_bool_and(Stage1AstGen *ag, Scope *scope, AstNode *node) } // block for when val1 == true - IrBasicBlockSrc *true_block = ir_create_basic_block(ag, scope, "BoolAndTrue"); + Stage1ZirBasicBlock *true_block = ir_create_basic_block(ag, scope, "BoolAndTrue"); // block for when val1 == false (don't even evaluate the second part) - IrBasicBlockSrc *false_block = ir_create_basic_block(ag, scope, "BoolAndFalse"); + Stage1ZirBasicBlock *false_block = ir_create_basic_block(ag, scope, "BoolAndFalse"); ir_build_cond_br(ag, scope, node, val1, true_block, false_block, is_comptime); @@ -3541,7 +3541,7 @@ static IrInstSrc *ir_gen_bool_and(Stage1AstGen *ag, Scope *scope, AstNode *node) IrInstSrc *val2 = ir_gen_node(ag, node->data.bin_op_expr.op2, scope); if (val2 == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; - IrBasicBlockSrc *post_val2_block = ag->current_basic_block; + Stage1ZirBasicBlock *post_val2_block = ag->current_basic_block; ir_build_br(ag, scope, node, false_block, is_comptime); @@ -3550,7 +3550,7 @@ static IrInstSrc *ir_gen_bool_and(Stage1AstGen *ag, Scope *scope, AstNode *node) IrInstSrc **incoming_values = heap::c_allocator.allocate(2); incoming_values[0] = val1; incoming_values[1] = val2; - IrBasicBlockSrc **incoming_blocks = heap::c_allocator.allocate(2); + Stage1ZirBasicBlock **incoming_blocks = heap::c_allocator.allocate(2); incoming_blocks[0] = post_val1_block; incoming_blocks[1] = post_val2_block; @@ -3558,7 +3558,7 @@ static IrInstSrc *ir_gen_bool_and(Stage1AstGen *ag, Scope *scope, AstNode *node) } static ResultLocPeerParent *ir_build_result_peers(Stage1AstGen *ag, IrInstSrc *cond_br_inst, - IrBasicBlockSrc *end_block, ResultLoc *parent, IrInstSrc *is_comptime) + Stage1ZirBasicBlock *end_block, ResultLoc *parent, IrInstSrc *is_comptime) { ResultLocPeerParent *peer_parent = heap::c_allocator.create(); peer_parent->base.id = ResultLocIdPeerParent; @@ -3578,7 +3578,7 @@ static ResultLocPeerParent *ir_build_result_peers(Stage1AstGen *ag, IrInstSrc *c } static ResultLocPeerParent *ir_build_binary_result_peers(Stage1AstGen *ag, IrInstSrc *cond_br_inst, - IrBasicBlockSrc *else_block, IrBasicBlockSrc *end_block, ResultLoc *parent, IrInstSrc *is_comptime) + Stage1ZirBasicBlock *else_block, Stage1ZirBasicBlock *end_block, ResultLoc *parent, IrInstSrc *is_comptime) { ResultLocPeerParent *peer_parent = ir_build_result_peers(ag, cond_br_inst, end_block, parent, is_comptime); @@ -3613,9 +3613,9 @@ static IrInstSrc *ir_gen_orelse(Stage1AstGen *ag, Scope *parent_scope, AstNode * is_comptime = ir_build_test_comptime(ag, parent_scope, node, is_non_null); } - IrBasicBlockSrc *ok_block = ir_create_basic_block(ag, parent_scope, "OptionalNonNull"); - IrBasicBlockSrc *null_block = ir_create_basic_block(ag, parent_scope, "OptionalNull"); - IrBasicBlockSrc *end_block = ir_create_basic_block(ag, parent_scope, "OptionalEnd"); + Stage1ZirBasicBlock *ok_block = ir_create_basic_block(ag, parent_scope, "OptionalNonNull"); + Stage1ZirBasicBlock *null_block = ir_create_basic_block(ag, parent_scope, "OptionalNull"); + Stage1ZirBasicBlock *end_block = ir_create_basic_block(ag, parent_scope, "OptionalEnd"); IrInstSrc *cond_br_inst = ir_build_cond_br(ag, parent_scope, node, is_non_null, ok_block, null_block, is_comptime); ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(ag, cond_br_inst, ok_block, end_block, @@ -3626,7 +3626,7 @@ static IrInstSrc *ir_gen_orelse(Stage1AstGen *ag, Scope *parent_scope, AstNode * &peer_parent->peers.at(0)->base); if (null_result == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; - IrBasicBlockSrc *after_null_block = ag->current_basic_block; + Stage1ZirBasicBlock *after_null_block = ag->current_basic_block; if (!instr_is_unreachable(null_result)) ir_mark_gen(ir_build_br(ag, parent_scope, node, end_block, is_comptime)); @@ -3634,14 +3634,14 @@ static IrInstSrc *ir_gen_orelse(Stage1AstGen *ag, Scope *parent_scope, AstNode * IrInstSrc *unwrapped_ptr = ir_build_optional_unwrap_ptr(ag, parent_scope, node, maybe_ptr, false); IrInstSrc *unwrapped_payload = ir_build_load_ptr(ag, parent_scope, node, unwrapped_ptr); ir_build_end_expr(ag, parent_scope, node, unwrapped_payload, &peer_parent->peers.at(1)->base); - IrBasicBlockSrc *after_ok_block = ag->current_basic_block; + Stage1ZirBasicBlock *after_ok_block = ag->current_basic_block; ir_build_br(ag, parent_scope, node, end_block, is_comptime); ir_set_cursor_at_end_and_append_block(ag, end_block); IrInstSrc **incoming_values = heap::c_allocator.allocate(2); incoming_values[0] = null_result; incoming_values[1] = unwrapped_payload; - IrBasicBlockSrc **incoming_blocks = heap::c_allocator.allocate(2); + Stage1ZirBasicBlock **incoming_blocks = heap::c_allocator.allocate(2); incoming_blocks[0] = after_null_block; incoming_blocks[1] = after_ok_block; IrInstSrc *phi = ir_build_phi(ag, parent_scope, node, 2, incoming_blocks, incoming_values, peer_parent); @@ -5372,9 +5372,9 @@ static IrInstSrc *ir_gen_if_bool_expr(Stage1AstGen *ag, Scope *scope, AstNode *n AstNode *then_node = node->data.if_bool_expr.then_block; AstNode *else_node = node->data.if_bool_expr.else_node; - IrBasicBlockSrc *then_block = ir_create_basic_block(ag, scope, "Then"); - IrBasicBlockSrc *else_block = ir_create_basic_block(ag, scope, "Else"); - IrBasicBlockSrc *endif_block = ir_create_basic_block(ag, scope, "EndIf"); + Stage1ZirBasicBlock *then_block = ir_create_basic_block(ag, scope, "Then"); + Stage1ZirBasicBlock *else_block = ir_create_basic_block(ag, scope, "Else"); + Stage1ZirBasicBlock *endif_block = ir_create_basic_block(ag, scope, "EndIf"); IrInstSrc *cond_br_inst = ir_build_cond_br(ag, scope, node, condition, then_block, else_block, is_comptime); @@ -5388,7 +5388,7 @@ static IrInstSrc *ir_gen_if_bool_expr(Stage1AstGen *ag, Scope *scope, AstNode *n &peer_parent->peers.at(0)->base); if (then_expr_result == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; - IrBasicBlockSrc *after_then_block = ag->current_basic_block; + Stage1ZirBasicBlock *after_then_block = ag->current_basic_block; if (!instr_is_unreachable(then_expr_result)) ir_mark_gen(ir_build_br(ag, scope, node, endif_block, is_comptime)); @@ -5402,7 +5402,7 @@ static IrInstSrc *ir_gen_if_bool_expr(Stage1AstGen *ag, Scope *scope, AstNode *n else_expr_result = ir_build_const_void(ag, scope, node); ir_build_end_expr(ag, scope, node, else_expr_result, &peer_parent->peers.at(1)->base); } - IrBasicBlockSrc *after_else_block = ag->current_basic_block; + Stage1ZirBasicBlock *after_else_block = ag->current_basic_block; if (!instr_is_unreachable(else_expr_result)) ir_mark_gen(ir_build_br(ag, scope, node, endif_block, is_comptime)); @@ -5410,7 +5410,7 @@ static IrInstSrc *ir_gen_if_bool_expr(Stage1AstGen *ag, Scope *scope, AstNode *n IrInstSrc **incoming_values = heap::c_allocator.allocate(2); incoming_values[0] = then_expr_result; incoming_values[1] = else_expr_result; - IrBasicBlockSrc **incoming_blocks = heap::c_allocator.allocate(2); + Stage1ZirBasicBlock **incoming_blocks = heap::c_allocator.allocate(2); incoming_blocks[0] = after_then_block; incoming_blocks[1] = after_else_block; @@ -5912,12 +5912,12 @@ static IrInstSrc *ir_gen_while_expr(Stage1AstGen *ag, Scope *scope, AstNode *nod AstNode *continue_expr_node = node->data.while_expr.continue_expr; AstNode *else_node = node->data.while_expr.else_node; - IrBasicBlockSrc *cond_block = ir_create_basic_block(ag, scope, "WhileCond"); - IrBasicBlockSrc *body_block = ir_create_basic_block(ag, scope, "WhileBody"); - IrBasicBlockSrc *continue_block = continue_expr_node ? + Stage1ZirBasicBlock *cond_block = ir_create_basic_block(ag, scope, "WhileCond"); + Stage1ZirBasicBlock *body_block = ir_create_basic_block(ag, scope, "WhileBody"); + Stage1ZirBasicBlock *continue_block = continue_expr_node ? ir_create_basic_block(ag, scope, "WhileContinue") : cond_block; - IrBasicBlockSrc *end_block = ir_create_basic_block(ag, scope, "WhileEnd"); - IrBasicBlockSrc *else_block = else_node ? + Stage1ZirBasicBlock *end_block = ir_create_basic_block(ag, scope, "WhileEnd"); + Stage1ZirBasicBlock *else_block = else_node ? ir_create_basic_block(ag, scope, "WhileElse") : end_block; IrInstSrc *is_comptime = ir_build_const_bool(ag, scope, node, @@ -5948,7 +5948,7 @@ static IrInstSrc *ir_gen_while_expr(Stage1AstGen *ag, Scope *scope, AstNode *nod return err_val_ptr; IrInstSrc *is_err = ir_build_test_err_src(ag, scope, node->data.while_expr.condition, err_val_ptr, true, false); - IrBasicBlockSrc *after_cond_block = ag->current_basic_block; + Stage1ZirBasicBlock *after_cond_block = ag->current_basic_block; IrInstSrc *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(ag, scope, node)); IrInstSrc *cond_br_inst; if (!instr_is_unreachable(is_err)) { @@ -5973,7 +5973,7 @@ static IrInstSrc *ir_gen_while_expr(Stage1AstGen *ag, Scope *scope, AstNode *nod } ZigList incoming_values = {0}; - ZigList incoming_blocks = {0}; + ZigList incoming_blocks = {0}; if (is_duplicate_label(ag->codegen, payload_scope, node, node->data.while_expr.name)) return ag->codegen->invalid_inst_src; @@ -6037,7 +6037,7 @@ static IrInstSrc *ir_gen_while_expr(Stage1AstGen *ag, Scope *scope, AstNode *nod return else_result; if (!instr_is_unreachable(else_result)) ir_mark_gen(ir_build_br(ag, scope, node, end_block, is_comptime)); - IrBasicBlockSrc *after_else_block = ag->current_basic_block; + Stage1ZirBasicBlock *after_else_block = ag->current_basic_block; ir_set_cursor_at_end_and_append_block(ag, end_block); if (else_result) { incoming_blocks.append(after_else_block); @@ -6069,7 +6069,7 @@ static IrInstSrc *ir_gen_while_expr(Stage1AstGen *ag, Scope *scope, AstNode *nod return maybe_val_ptr; IrInstSrc *maybe_val = ir_build_load_ptr(ag, scope, node->data.while_expr.condition, maybe_val_ptr); IrInstSrc *is_non_null = ir_build_test_non_null_src(ag, scope, node->data.while_expr.condition, maybe_val); - IrBasicBlockSrc *after_cond_block = ag->current_basic_block; + Stage1ZirBasicBlock *after_cond_block = ag->current_basic_block; IrInstSrc *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(ag, scope, node)); IrInstSrc *cond_br_inst; if (!instr_is_unreachable(is_non_null)) { @@ -6091,7 +6091,7 @@ static IrInstSrc *ir_gen_while_expr(Stage1AstGen *ag, Scope *scope, AstNode *nod build_decl_var_and_init(ag, child_scope, symbol_node, payload_var, var_value, buf_ptr(var_symbol), is_comptime); ZigList incoming_values = {0}; - ZigList incoming_blocks = {0}; + ZigList incoming_blocks = {0}; if (is_duplicate_label(ag->codegen, child_scope, node, node->data.while_expr.name)) return ag->codegen->invalid_inst_src; @@ -6148,7 +6148,7 @@ static IrInstSrc *ir_gen_while_expr(Stage1AstGen *ag, Scope *scope, AstNode *nod if (!instr_is_unreachable(else_result)) ir_mark_gen(ir_build_br(ag, scope, node, end_block, is_comptime)); } - IrBasicBlockSrc *after_else_block = ag->current_basic_block; + Stage1ZirBasicBlock *after_else_block = ag->current_basic_block; ir_set_cursor_at_end_and_append_block(ag, end_block); if (else_result) { incoming_blocks.append(after_else_block); @@ -6169,7 +6169,7 @@ static IrInstSrc *ir_gen_while_expr(Stage1AstGen *ag, Scope *scope, AstNode *nod IrInstSrc *cond_val = ir_gen_node(ag, node->data.while_expr.condition, scope); if (cond_val == ag->codegen->invalid_inst_src) return cond_val; - IrBasicBlockSrc *after_cond_block = ag->current_basic_block; + Stage1ZirBasicBlock *after_cond_block = ag->current_basic_block; IrInstSrc *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(ag, scope, node)); IrInstSrc *cond_br_inst; if (!instr_is_unreachable(cond_val)) { @@ -6186,7 +6186,7 @@ static IrInstSrc *ir_gen_while_expr(Stage1AstGen *ag, Scope *scope, AstNode *nod ir_set_cursor_at_end_and_append_block(ag, body_block); ZigList incoming_values = {0}; - ZigList incoming_blocks = {0}; + ZigList incoming_blocks = {0}; Scope *subexpr_scope = create_runtime_scope(ag->codegen, node, scope, is_comptime); @@ -6245,7 +6245,7 @@ static IrInstSrc *ir_gen_while_expr(Stage1AstGen *ag, Scope *scope, AstNode *nod if (!instr_is_unreachable(else_result)) ir_mark_gen(ir_build_br(ag, scope, node, end_block, is_comptime)); } - IrBasicBlockSrc *after_else_block = ag->current_basic_block; + Stage1ZirBasicBlock *after_else_block = ag->current_basic_block; ir_set_cursor_at_end_and_append_block(ag, end_block); if (else_result) { incoming_blocks.append(after_else_block); @@ -6312,11 +6312,11 @@ static IrInstSrc *ir_gen_for_expr(Stage1AstGen *ag, Scope *parent_scope, AstNode IrInstSrc *index_ptr = ir_build_var_ptr(ag, parent_scope, node, index_var); - IrBasicBlockSrc *cond_block = ir_create_basic_block(ag, parent_scope, "ForCond"); - IrBasicBlockSrc *body_block = ir_create_basic_block(ag, parent_scope, "ForBody"); - IrBasicBlockSrc *end_block = ir_create_basic_block(ag, parent_scope, "ForEnd"); - IrBasicBlockSrc *else_block = else_node ? ir_create_basic_block(ag, parent_scope, "ForElse") : end_block; - IrBasicBlockSrc *continue_block = ir_create_basic_block(ag, parent_scope, "ForContinue"); + Stage1ZirBasicBlock *cond_block = ir_create_basic_block(ag, parent_scope, "ForCond"); + Stage1ZirBasicBlock *body_block = ir_create_basic_block(ag, parent_scope, "ForBody"); + Stage1ZirBasicBlock *end_block = ir_create_basic_block(ag, parent_scope, "ForEnd"); + Stage1ZirBasicBlock *else_block = else_node ? ir_create_basic_block(ag, parent_scope, "ForElse") : end_block; + Stage1ZirBasicBlock *continue_block = ir_create_basic_block(ag, parent_scope, "ForContinue"); Buf *len_field_name = buf_create_from_str("len"); IrInstSrc *len_ref = ir_build_field_ptr(ag, parent_scope, node, array_val_ptr, len_field_name, false); @@ -6326,7 +6326,7 @@ static IrInstSrc *ir_gen_for_expr(Stage1AstGen *ag, Scope *parent_scope, AstNode ir_set_cursor_at_end_and_append_block(ag, cond_block); IrInstSrc *index_val = ir_build_load_ptr(ag, &spill_scope->base, node, index_ptr); IrInstSrc *cond = ir_build_bin_op(ag, parent_scope, node, IrBinOpCmpLessThan, index_val, len_val, false); - IrBasicBlockSrc *after_cond_block = ag->current_basic_block; + Stage1ZirBasicBlock *after_cond_block = ag->current_basic_block; IrInstSrc *void_else_value = else_node ? nullptr : ir_mark_gen(ir_build_const_void(ag, parent_scope, node)); IrInstSrc *cond_br_inst = ir_mark_gen(ir_build_cond_br(ag, parent_scope, node, cond, body_block, else_block, is_comptime)); @@ -6349,7 +6349,7 @@ static IrInstSrc *ir_gen_for_expr(Stage1AstGen *ag, Scope *parent_scope, AstNode return ag->codegen->invalid_inst_src; ZigList incoming_values = {0}; - ZigList incoming_blocks = {0}; + ZigList incoming_blocks = {0}; ScopeLoop *loop_scope = create_loop_scope(ag->codegen, node, child_scope); loop_scope->break_block = end_block; loop_scope->continue_block = continue_block; @@ -6396,7 +6396,7 @@ static IrInstSrc *ir_gen_for_expr(Stage1AstGen *ag, Scope *parent_scope, AstNode if (!instr_is_unreachable(else_result)) ir_mark_gen(ir_build_br(ag, parent_scope, node, end_block, is_comptime)); } - IrBasicBlockSrc *after_else_block = ag->current_basic_block; + Stage1ZirBasicBlock *after_else_block = ag->current_basic_block; ir_set_cursor_at_end_and_append_block(ag, end_block); if (else_result) { @@ -6667,9 +6667,9 @@ static IrInstSrc *ir_gen_if_optional_expr(Stage1AstGen *ag, Scope *scope, AstNod IrInstSrc *maybe_val = ir_build_load_ptr(ag, scope, node, maybe_val_ptr); IrInstSrc *is_non_null = ir_build_test_non_null_src(ag, scope, node, maybe_val); - IrBasicBlockSrc *then_block = ir_create_basic_block(ag, scope, "OptionalThen"); - IrBasicBlockSrc *else_block = ir_create_basic_block(ag, scope, "OptionalElse"); - IrBasicBlockSrc *endif_block = ir_create_basic_block(ag, scope, "OptionalEndIf"); + Stage1ZirBasicBlock *then_block = ir_create_basic_block(ag, scope, "OptionalThen"); + Stage1ZirBasicBlock *else_block = ir_create_basic_block(ag, scope, "OptionalElse"); + Stage1ZirBasicBlock *endif_block = ir_create_basic_block(ag, scope, "OptionalEndIf"); IrInstSrc *is_comptime; if (ir_should_inline(ag->exec, scope)) { @@ -6705,7 +6705,7 @@ static IrInstSrc *ir_gen_if_optional_expr(Stage1AstGen *ag, Scope *scope, AstNod &peer_parent->peers.at(0)->base); if (then_expr_result == ag->codegen->invalid_inst_src) return then_expr_result; - IrBasicBlockSrc *after_then_block = ag->current_basic_block; + Stage1ZirBasicBlock *after_then_block = ag->current_basic_block; if (!instr_is_unreachable(then_expr_result)) ir_mark_gen(ir_build_br(ag, scope, node, endif_block, is_comptime)); @@ -6719,7 +6719,7 @@ static IrInstSrc *ir_gen_if_optional_expr(Stage1AstGen *ag, Scope *scope, AstNod else_expr_result = ir_build_const_void(ag, scope, node); ir_build_end_expr(ag, scope, node, else_expr_result, &peer_parent->peers.at(1)->base); } - IrBasicBlockSrc *after_else_block = ag->current_basic_block; + Stage1ZirBasicBlock *after_else_block = ag->current_basic_block; if (!instr_is_unreachable(else_expr_result)) ir_mark_gen(ir_build_br(ag, scope, node, endif_block, is_comptime)); @@ -6727,7 +6727,7 @@ static IrInstSrc *ir_gen_if_optional_expr(Stage1AstGen *ag, Scope *scope, AstNod IrInstSrc **incoming_values = heap::c_allocator.allocate(2); incoming_values[0] = then_expr_result; incoming_values[1] = else_expr_result; - IrBasicBlockSrc **incoming_blocks = heap::c_allocator.allocate(2); + Stage1ZirBasicBlock **incoming_blocks = heap::c_allocator.allocate(2); incoming_blocks[0] = after_then_block; incoming_blocks[1] = after_else_block; @@ -6755,9 +6755,9 @@ static IrInstSrc *ir_gen_if_err_expr(Stage1AstGen *ag, Scope *scope, AstNode *no IrInstSrc *err_val = ir_build_load_ptr(ag, scope, node, err_val_ptr); IrInstSrc *is_err = ir_build_test_err_src(ag, scope, node, err_val_ptr, true, false); - IrBasicBlockSrc *ok_block = ir_create_basic_block(ag, scope, "TryOk"); - IrBasicBlockSrc *else_block = ir_create_basic_block(ag, scope, "TryElse"); - IrBasicBlockSrc *endif_block = ir_create_basic_block(ag, scope, "TryEnd"); + Stage1ZirBasicBlock *ok_block = ir_create_basic_block(ag, scope, "TryOk"); + Stage1ZirBasicBlock *else_block = ir_create_basic_block(ag, scope, "TryElse"); + Stage1ZirBasicBlock *endif_block = ir_create_basic_block(ag, scope, "TryEnd"); bool force_comptime = ir_should_inline(ag->exec, scope); IrInstSrc *is_comptime = force_comptime ? ir_build_const_bool(ag, scope, node, true) : ir_build_test_comptime(ag, scope, node, is_err); @@ -6788,7 +6788,7 @@ static IrInstSrc *ir_gen_if_err_expr(Stage1AstGen *ag, Scope *scope, AstNode *no &peer_parent->peers.at(0)->base); if (then_expr_result == ag->codegen->invalid_inst_src) return then_expr_result; - IrBasicBlockSrc *after_then_block = ag->current_basic_block; + Stage1ZirBasicBlock *after_then_block = ag->current_basic_block; if (!instr_is_unreachable(then_expr_result)) ir_mark_gen(ir_build_br(ag, scope, node, endif_block, is_comptime)); @@ -6817,7 +6817,7 @@ static IrInstSrc *ir_gen_if_err_expr(Stage1AstGen *ag, Scope *scope, AstNode *no else_expr_result = ir_build_const_void(ag, scope, node); ir_build_end_expr(ag, scope, node, else_expr_result, &peer_parent->peers.at(1)->base); } - IrBasicBlockSrc *after_else_block = ag->current_basic_block; + Stage1ZirBasicBlock *after_else_block = ag->current_basic_block; if (!instr_is_unreachable(else_expr_result)) ir_mark_gen(ir_build_br(ag, scope, node, endif_block, is_comptime)); @@ -6825,7 +6825,7 @@ static IrInstSrc *ir_gen_if_err_expr(Stage1AstGen *ag, Scope *scope, AstNode *no IrInstSrc **incoming_values = heap::c_allocator.allocate(2); incoming_values[0] = then_expr_result; incoming_values[1] = else_expr_result; - IrBasicBlockSrc **incoming_blocks = heap::c_allocator.allocate(2); + Stage1ZirBasicBlock **incoming_blocks = heap::c_allocator.allocate(2); incoming_blocks[0] = after_then_block; incoming_blocks[1] = after_else_block; @@ -6834,9 +6834,9 @@ static IrInstSrc *ir_gen_if_err_expr(Stage1AstGen *ag, Scope *scope, AstNode *no } static bool ir_gen_switch_prong_expr(Stage1AstGen *ag, Scope *scope, AstNode *switch_node, AstNode *prong_node, - IrBasicBlockSrc *end_block, IrInstSrc *is_comptime, IrInstSrc *var_is_comptime, + Stage1ZirBasicBlock *end_block, IrInstSrc *is_comptime, IrInstSrc *var_is_comptime, IrInstSrc *target_value_ptr, IrInstSrc **prong_values, size_t prong_values_len, - ZigList *incoming_blocks, ZigList *incoming_values, + ZigList *incoming_blocks, ZigList *incoming_values, IrInstSrcSwitchElseVar **out_switch_else_var, LVal lval, ResultLoc *result_loc) { assert(switch_node->type == NodeTypeSwitchExpr); @@ -6898,8 +6898,8 @@ static IrInstSrc *ir_gen_switch_expr(Stage1AstGen *ag, Scope *scope, AstNode *no return target_value_ptr; IrInstSrc *target_value = ir_build_switch_target(ag, scope, node, target_value_ptr); - IrBasicBlockSrc *else_block = ir_create_basic_block(ag, scope, "SwitchElse"); - IrBasicBlockSrc *end_block = ir_create_basic_block(ag, scope, "SwitchEnd"); + Stage1ZirBasicBlock *else_block = ir_create_basic_block(ag, scope, "SwitchElse"); + Stage1ZirBasicBlock *end_block = ir_create_basic_block(ag, scope, "SwitchEnd"); size_t prong_count = node->data.switch_expr.prongs.length; ZigList cases = {0}; @@ -6915,7 +6915,7 @@ static IrInstSrc *ir_gen_switch_expr(Stage1AstGen *ag, Scope *scope, AstNode *no } ZigList incoming_values = {0}; - ZigList incoming_blocks = {0}; + ZigList incoming_blocks = {0}; ZigList check_ranges = {0}; IrInstSrcSwitchElseVar *switch_else_var = nullptr; @@ -6991,8 +6991,8 @@ static IrInstSrc *ir_gen_switch_expr(Stage1AstGen *ag, Scope *scope, AstNode *no } } - IrBasicBlockSrc *range_block_yes = ir_create_basic_block(ag, scope, "SwitchRangeYes"); - IrBasicBlockSrc *range_block_no = ir_create_basic_block(ag, scope, "SwitchRangeNo"); + Stage1ZirBasicBlock *range_block_yes = ir_create_basic_block(ag, scope, "SwitchRangeYes"); + Stage1ZirBasicBlock *range_block_no = ir_create_basic_block(ag, scope, "SwitchRangeNo"); assert(ok_bit); assert(last_item_node); @@ -7052,7 +7052,7 @@ static IrInstSrc *ir_gen_switch_expr(Stage1AstGen *ag, Scope *scope, AstNode *no } ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent); - IrBasicBlockSrc *prev_block = ag->current_basic_block; + Stage1ZirBasicBlock *prev_block = ag->current_basic_block; if (peer_parent->peers.length > 0) { peer_parent->peers.last()->next_bb = else_block; } @@ -7081,7 +7081,7 @@ static IrInstSrc *ir_gen_switch_expr(Stage1AstGen *ag, Scope *scope, AstNode *no ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent); - IrBasicBlockSrc *prong_block = ir_create_basic_block(ag, scope, "SwitchProng"); + Stage1ZirBasicBlock *prong_block = ir_create_basic_block(ag, scope, "SwitchProng"); IrInstSrc **items = heap::c_allocator.allocate(prong_item_count); for (size_t item_i = 0; item_i < prong_item_count; item_i += 1) { @@ -7103,7 +7103,7 @@ static IrInstSrc *ir_gen_switch_expr(Stage1AstGen *ag, Scope *scope, AstNode *no items[item_i] = item_value; } - IrBasicBlockSrc *prev_block = ag->current_basic_block; + Stage1ZirBasicBlock *prev_block = ag->current_basic_block; if (peer_parent->peers.length > 0) { peer_parent->peers.last()->next_bb = prong_block; } @@ -7202,7 +7202,7 @@ static IrInstSrc *ir_gen_return_from_block(Stage1AstGen *ag, Scope *break_scope, result_value = ir_build_const_void(ag, break_scope, node); } - IrBasicBlockSrc *dest_block = block_scope->end_block; + Stage1ZirBasicBlock *dest_block = block_scope->end_block; if (!ir_gen_defers_for_block(ag, break_scope, dest_block->scope, nullptr, nullptr)) return ag->codegen->invalid_inst_src; @@ -7279,7 +7279,7 @@ static IrInstSrc *ir_gen_break(Stage1AstGen *ag, Scope *break_scope, AstNode *no result_value = ir_build_const_void(ag, break_scope, node); } - IrBasicBlockSrc *dest_block = loop_scope->break_block; + Stage1ZirBasicBlock *dest_block = loop_scope->break_block; if (!ir_gen_defers_for_block(ag, break_scope, dest_block->scope, nullptr, nullptr)) return ag->codegen->invalid_inst_src; @@ -7341,7 +7341,7 @@ static IrInstSrc *ir_gen_continue(Stage1AstGen *ag, Scope *continue_scope, AstNo } runtime_scopes.deinit(); - IrBasicBlockSrc *dest_block = loop_scope->continue_block; + Stage1ZirBasicBlock *dest_block = loop_scope->continue_block; if (!ir_gen_defers_for_block(ag, continue_scope, dest_block->scope, nullptr, nullptr)) return ag->codegen->invalid_inst_src; return ir_mark_gen(ir_build_br(ag, continue_scope, node, dest_block, is_comptime)); @@ -7440,9 +7440,9 @@ static IrInstSrc *ir_gen_catch(Stage1AstGen *ag, Scope *parent_scope, AstNode *n is_comptime = ir_build_test_comptime(ag, parent_scope, node, is_err); } - IrBasicBlockSrc *ok_block = ir_create_basic_block(ag, parent_scope, "UnwrapErrOk"); - IrBasicBlockSrc *err_block = ir_create_basic_block(ag, parent_scope, "UnwrapErrError"); - IrBasicBlockSrc *end_block = ir_create_basic_block(ag, parent_scope, "UnwrapErrEnd"); + Stage1ZirBasicBlock *ok_block = ir_create_basic_block(ag, parent_scope, "UnwrapErrOk"); + Stage1ZirBasicBlock *err_block = ir_create_basic_block(ag, parent_scope, "UnwrapErrError"); + Stage1ZirBasicBlock *end_block = ir_create_basic_block(ag, parent_scope, "UnwrapErrEnd"); IrInstSrc *cond_br_inst = ir_build_cond_br(ag, parent_scope, node, is_err, err_block, ok_block, is_comptime); ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(ag, cond_br_inst, ok_block, end_block, result_loc, @@ -7468,7 +7468,7 @@ static IrInstSrc *ir_gen_catch(Stage1AstGen *ag, Scope *parent_scope, AstNode *n IrInstSrc *err_result = ir_gen_node_extra(ag, op2_node, err_scope, LValNone, &peer_parent->peers.at(0)->base); if (err_result == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; - IrBasicBlockSrc *after_err_block = ag->current_basic_block; + Stage1ZirBasicBlock *after_err_block = ag->current_basic_block; if (!instr_is_unreachable(err_result)) ir_mark_gen(ir_build_br(ag, parent_scope, node, end_block, is_comptime)); @@ -7476,14 +7476,14 @@ static IrInstSrc *ir_gen_catch(Stage1AstGen *ag, Scope *parent_scope, AstNode *n IrInstSrc *unwrapped_ptr = ir_build_unwrap_err_payload_src(ag, parent_scope, node, err_union_ptr, false, false); IrInstSrc *unwrapped_payload = ir_build_load_ptr(ag, parent_scope, node, unwrapped_ptr); ir_build_end_expr(ag, parent_scope, node, unwrapped_payload, &peer_parent->peers.at(1)->base); - IrBasicBlockSrc *after_ok_block = ag->current_basic_block; + Stage1ZirBasicBlock *after_ok_block = ag->current_basic_block; ir_build_br(ag, parent_scope, node, end_block, is_comptime); ir_set_cursor_at_end_and_append_block(ag, end_block); IrInstSrc **incoming_values = heap::c_allocator.allocate(2); incoming_values[0] = err_result; incoming_values[1] = unwrapped_payload; - IrBasicBlockSrc **incoming_blocks = heap::c_allocator.allocate(2); + Stage1ZirBasicBlock **incoming_blocks = heap::c_allocator.allocate(2); incoming_blocks[0] = after_err_block; incoming_blocks[1] = after_ok_block; IrInstSrc *phi = ir_build_phi(ag, parent_scope, node, 2, incoming_blocks, incoming_values, peer_parent); @@ -8045,7 +8045,7 @@ bool stage1_astgen(CodeGen *codegen, AstNode *node, Scope *scope, Stage1Zir *sta ag->exec = stage1_zir; ag->main_block_node = node; - IrBasicBlockSrc *entry_block = ir_create_basic_block(ag, scope, "Entry"); + Stage1ZirBasicBlock *entry_block = ir_create_basic_block(ag, scope, "Entry"); ir_set_cursor_at_end_and_append_block(ag, entry_block); // Entry block gets a reference because we enter it to begin. ir_ref_bb(ag->current_basic_block); diff --git a/src/stage1/ir.cpp b/src/stage1/ir.cpp index 9188c746da..3604f98ff5 100644 --- a/src/stage1/ir.cpp +++ b/src/stage1/ir.cpp @@ -34,7 +34,7 @@ struct IrBuilderGen { struct IrAnalyze { CodeGen *codegen; Stage1Zir *zir; - IrBasicBlockSrc *zir_current_basic_block; + Stage1ZirBasicBlock *zir_current_basic_block; IrBuilderGen new_irb; size_t old_bb_index; size_t instruction_index; @@ -42,7 +42,7 @@ struct IrAnalyze { AstNode *explicit_return_type_source_node; ZigList src_implicit_return_type_list; ZigList resume_stack; - IrBasicBlockSrc *const_predecessor_bb; + Stage1ZirBasicBlock *const_predecessor_bb; size_t ref_count; size_t break_debug_id; // for debugging purposes IrInstGen *return_ptr; @@ -482,7 +482,7 @@ static void ira_deref(IrAnalyze *ira) { assert(ira->ref_count != 0); for (size_t bb_i = 0; bb_i < ira->zir->basic_block_list.length; bb_i += 1) { - IrBasicBlockSrc *pass1_bb = ira->zir->basic_block_list.items[bb_i]; + Stage1ZirBasicBlock *pass1_bb = ira->zir->basic_block_list.items[bb_i]; for (size_t inst_i = 0; inst_i < pass1_bb->instruction_list.length; inst_i += 1) { IrInstSrc *pass1_inst = pass1_bb->instruction_list.items[inst_i]; destroy_instruction_src(pass1_inst); @@ -742,7 +742,7 @@ static IrBasicBlockGen *ir_create_basic_block_gen(IrAnalyze *ira, Scope *scope, return result; } -static IrBasicBlockGen *ir_build_bb_from(IrAnalyze *ira, IrBasicBlockSrc *other_bb) { +static IrBasicBlockGen *ir_build_bb_from(IrAnalyze *ira, Stage1ZirBasicBlock *other_bb) { IrBasicBlockGen *new_bb = ir_create_basic_block_gen(ira, other_bb->scope, other_bb->name_hint); other_bb->child = new_bb; return new_bb; @@ -5261,7 +5261,7 @@ static IrInstGen *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInst* sourc return ir_build_ptr_of_array_to_slice(ira, source_instr, wanted_type, array_ptr, result_loc_inst); } -static IrBasicBlockGen *ir_get_new_bb(IrAnalyze *ira, IrBasicBlockSrc *old_bb, IrInst *ref_old_instruction) { +static IrBasicBlockGen *ir_get_new_bb(IrAnalyze *ira, Stage1ZirBasicBlock *old_bb, IrInst *ref_old_instruction) { assert(old_bb); if (old_bb->child) { @@ -5276,7 +5276,7 @@ static IrBasicBlockGen *ir_get_new_bb(IrAnalyze *ira, IrBasicBlockSrc *old_bb, I return new_bb; } -static IrBasicBlockGen *ir_get_new_bb_runtime(IrAnalyze *ira, IrBasicBlockSrc *old_bb, IrInst *ref_old_instruction) { +static IrBasicBlockGen *ir_get_new_bb_runtime(IrAnalyze *ira, Stage1ZirBasicBlock *old_bb, IrInst *ref_old_instruction) { assert(ref_old_instruction != nullptr); IrBasicBlockGen *new_bb = ir_get_new_bb(ira, old_bb, ref_old_instruction); if (new_bb->must_be_comptime_source_instr) { @@ -5289,7 +5289,7 @@ static IrBasicBlockGen *ir_get_new_bb_runtime(IrAnalyze *ira, IrBasicBlockSrc *o return new_bb; } -static void ir_start_bb(IrAnalyze *ira, IrBasicBlockSrc *old_bb, IrBasicBlockSrc *const_predecessor_bb) { +static void ir_start_bb(IrAnalyze *ira, Stage1ZirBasicBlock *old_bb, Stage1ZirBasicBlock *const_predecessor_bb) { ir_assert(!old_bb->suspended, (old_bb->instruction_list.length != 0) ? &old_bb->instruction_list.at(0)->base : nullptr); ira->instruction_index = 0; ira->zir_current_basic_block = old_bb; @@ -5297,7 +5297,7 @@ static void ir_start_bb(IrAnalyze *ira, IrBasicBlockSrc *old_bb, IrBasicBlockSrc ira->old_bb_index = old_bb->index; } -static IrInstGen *ira_suspend(IrAnalyze *ira, IrInst *old_instruction, IrBasicBlockSrc *next_bb, +static IrInstGen *ira_suspend(IrAnalyze *ira, IrInst *old_instruction, Stage1ZirBasicBlock *next_bb, IrSuspendPosition *suspend_pos) { if (ira->codegen->verbose_ir) { @@ -5356,7 +5356,7 @@ static void ir_start_next_bb(IrAnalyze *ira) { bool need_repeat = true; for (;;) { while (ira->old_bb_index < ira->zir->basic_block_list.length) { - IrBasicBlockSrc *old_bb = ira->zir->basic_block_list.at(ira->old_bb_index); + Stage1ZirBasicBlock *old_bb = ira->zir->basic_block_list.at(ira->old_bb_index); if (old_bb->child == nullptr && old_bb->suspend_instruction_ref == nullptr) { ira->old_bb_index += 1; continue; @@ -5447,7 +5447,7 @@ static bool ir_emit_backward_branch(IrAnalyze *ira, IrInst* source_instruction) return true; } -static IrInstGen *ir_inline_bb(IrAnalyze *ira, IrInst* source_instruction, IrBasicBlockSrc *old_bb) { +static IrInstGen *ir_inline_bb(IrAnalyze *ira, IrInst* source_instruction, Stage1ZirBasicBlock *old_bb) { if (old_bb->debug_id <= ira->zir_current_basic_block->debug_id) { if (!ir_emit_backward_branch(ira, source_instruction)) return ir_unreach_error(ira); @@ -13776,20 +13776,20 @@ static IrInstGen *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstSrcUnOp *in } static void ir_push_resume(IrAnalyze *ira, IrSuspendPosition pos) { - IrBasicBlockSrc *old_bb = ira->zir->basic_block_list.at(pos.basic_block_index); + Stage1ZirBasicBlock *old_bb = ira->zir->basic_block_list.at(pos.basic_block_index); if (old_bb->in_resume_stack) return; ira->resume_stack.append(pos); old_bb->in_resume_stack = true; } -static void ir_push_resume_block(IrAnalyze *ira, IrBasicBlockSrc *old_bb) { +static void ir_push_resume_block(IrAnalyze *ira, Stage1ZirBasicBlock *old_bb) { if (ira->resume_stack.length != 0) { ir_push_resume(ira, {old_bb->index, 0}); } } static IrInstGen *ir_analyze_instruction_br(IrAnalyze *ira, IrInstSrcBr *br_instruction) { - IrBasicBlockSrc *old_dest_block = br_instruction->dest_block; + Stage1ZirBasicBlock *old_dest_block = br_instruction->dest_block; bool is_comptime; if (!ir_resolve_comptime(ira, br_instruction->is_comptime->child, &is_comptime)) @@ -13827,7 +13827,7 @@ static IrInstGen *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstSrcCondBr if (!ir_resolve_bool(ira, casted_condition, &cond_is_true)) return ir_unreach_error(ira); - IrBasicBlockSrc *old_dest_block = cond_is_true ? + Stage1ZirBasicBlock *old_dest_block = cond_is_true ? cond_br_instruction->then_block : cond_br_instruction->else_block; if (is_comptime || (old_dest_block->ref_count == 1 && old_dest_block->suspend_instruction_ref == nullptr)) @@ -13877,7 +13877,7 @@ static IrInstGen *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstSrcPhi *phi_i if (ira->const_predecessor_bb) { for (size_t i = 0; i < phi_instruction->incoming_count; i += 1) { - IrBasicBlockSrc *predecessor = phi_instruction->incoming_blocks[i]; + Stage1ZirBasicBlock *predecessor = phi_instruction->incoming_blocks[i]; if (predecessor != ira->const_predecessor_bb) continue; IrInstGen *value = phi_instruction->incoming_values[i]->child; @@ -13977,7 +13977,7 @@ static IrInstGen *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstSrcPhi *phi_i ZigList new_incoming_values = {0}; for (size_t i = 0; i < phi_instruction->incoming_count; i += 1) { - IrBasicBlockSrc *predecessor = phi_instruction->incoming_blocks[i]; + Stage1ZirBasicBlock *predecessor = phi_instruction->incoming_blocks[i]; if (predecessor->ref_count == 0) continue; @@ -15996,7 +15996,7 @@ static IrInstGen *ir_analyze_instruction_switch_br(IrAnalyze *ira, if (!target_val) return ir_unreach_error(ira); - IrBasicBlockSrc *old_dest_block = switch_br_instruction->else_block; + Stage1ZirBasicBlock *old_dest_block = switch_br_instruction->else_block; for (size_t i = 0; i < case_count; i += 1) { IrInstSrcSwitchBrCase *old_case = &switch_br_instruction->cases[i]; IrInstGen *case_value = old_case->value->child; @@ -24488,7 +24488,7 @@ ZigType *ir_analyze(CodeGen *codegen, Stage1Zir *stage1_zir, Stage1Air *stage1_a ira->new_irb.codegen = codegen; ira->new_irb.exec = stage1_air; - IrBasicBlockSrc *old_entry_bb = ira->zir->basic_block_list.at(0); + Stage1ZirBasicBlock *old_entry_bb = ira->zir->basic_block_list.at(0); IrBasicBlockGen *new_entry_bb = ir_get_new_bb(ira, old_entry_bb, nullptr); ira->new_irb.current_basic_block = new_entry_bb; ira->old_bb_index = 0; diff --git a/src/stage1/ir_print.cpp b/src/stage1/ir_print.cpp index c9b80b8675..ef3bda60d2 100644 --- a/src/stage1/ir_print.cpp +++ b/src/stage1/ir_print.cpp @@ -633,7 +633,7 @@ static void ir_print_other_inst_gen(IrPrintGen *irp, IrInstGen *inst) { } } -static void ir_print_other_block(IrPrintSrc *irp, IrBasicBlockSrc *bb) { +static void ir_print_other_block(IrPrintSrc *irp, Stage1ZirBasicBlock *bb) { if (bb == nullptr) { fprintf(irp->f, "(null block)"); } else { @@ -1006,7 +1006,7 @@ static void ir_print_phi(IrPrintSrc *irp, IrInstSrcPhi *phi_instruction) { assert(phi_instruction->incoming_count != 0); assert(phi_instruction->incoming_count != SIZE_MAX); for (size_t i = 0; i < phi_instruction->incoming_count; i += 1) { - IrBasicBlockSrc *incoming_block = phi_instruction->incoming_blocks[i]; + Stage1ZirBasicBlock *incoming_block = phi_instruction->incoming_blocks[i]; IrInstSrc *incoming_value = phi_instruction->incoming_values[i]; if (i != 0) fprintf(irp->f, " "); @@ -3350,7 +3350,7 @@ static void ir_print_inst_gen(IrPrintGen *irp, IrInstGen *instruction, bool trai fprintf(irp->f, "\n"); } -static void irp_print_basic_block_src(IrPrintSrc *irp, IrBasicBlockSrc *current_block) { +static void irp_print_basic_block_src(IrPrintSrc *irp, Stage1ZirBasicBlock *current_block) { fprintf(irp->f, "%s_%" PRIu32 ":\n", current_block->name_hint, current_block->debug_id); for (size_t instr_i = 0; instr_i < current_block->instruction_list.length; instr_i += 1) { IrInstSrc *instruction = current_block->instruction_list.at(instr_i); @@ -3370,7 +3370,7 @@ static void irp_print_basic_block_gen(IrPrintGen *irp, IrBasicBlockGen *current_ } } -void ir_print_basic_block_src(CodeGen *codegen, FILE *f, IrBasicBlockSrc *bb, int indent_size) { +void ir_print_basic_block_src(CodeGen *codegen, FILE *f, Stage1ZirBasicBlock *bb, int indent_size) { IrPrintSrc ir_print = {}; ir_print.codegen = codegen; ir_print.f = f; diff --git a/src/stage1/ir_print.hpp b/src/stage1/ir_print.hpp index bec75be515..ec325adfa6 100644 --- a/src/stage1/ir_print.hpp +++ b/src/stage1/ir_print.hpp @@ -16,7 +16,7 @@ void ir_print_src(CodeGen *codegen, FILE *f, Stage1Zir *executable, int indent_s void ir_print_gen(CodeGen *codegen, FILE *f, Stage1Air *executable, int indent_size); void ir_print_inst_src(CodeGen *codegen, FILE *f, IrInstSrc *inst, int indent_size); void ir_print_inst_gen(CodeGen *codegen, FILE *f, IrInstGen *inst, int indent_size); -void ir_print_basic_block_src(CodeGen *codegen, FILE *f, IrBasicBlockSrc *bb, int indent_size); +void ir_print_basic_block_src(CodeGen *codegen, FILE *f, Stage1ZirBasicBlock *bb, int indent_size); void ir_print_basic_block_gen(CodeGen *codegen, FILE *f, IrBasicBlockGen *bb, int indent_size); const char* ir_inst_src_type_str(IrInstSrcId id); From 9de2c1b76e2b38e35bb17cd0a3943a61c730da76 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 28 May 2021 13:26:16 -0700 Subject: [PATCH 11/14] stage1: tokenizer: backport recent stage2 changes This backports ec10595b65490126e1b7d231f655be6d7d198acf stage2 tokenizer logic to stage1. --- src/stage1/tokenizer.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/stage1/tokenizer.cpp b/src/stage1/tokenizer.cpp index b1bae1865b..49d5d80fb0 100644 --- a/src/stage1/tokenizer.cpp +++ b/src/stage1/tokenizer.cpp @@ -1290,12 +1290,9 @@ void tokenize(const char *source, Tokenization *out) { case DIGIT: t.state = TokenizeState_float_fraction_dec; break; - case ALPHA_EXCEPT_E: + default: invalid_char_error(&t, c); break; - default: - t.state = TokenizeState_start; - continue; } break; case TokenizeState_num_dot_hex: @@ -1316,12 +1313,9 @@ void tokenize(const char *source, Tokenization *out) { t.out->ids.last() = TokenIdFloatLiteral; t.state = TokenizeState_float_fraction_hex; break; - case ALPHA_EXCEPT_HEX_AND_P: + default: invalid_char_error(&t, c); break; - default: - t.state = TokenizeState_start; - continue; } break; case TokenizeState_float_fraction_dec_no_underscore: From 52b3daa90ee41ba7e059331cf7541eb8570ec236 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 28 May 2021 14:19:08 -0700 Subject: [PATCH 12/14] stage1: get test-compile-errors passing again --- src/stage1/tokenizer.cpp | 5 ++++- test/compile_errors.zig | 8 ++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/stage1/tokenizer.cpp b/src/stage1/tokenizer.cpp index 49d5d80fb0..873a48b327 100644 --- a/src/stage1/tokenizer.cpp +++ b/src/stage1/tokenizer.cpp @@ -747,6 +747,9 @@ void tokenize(const char *source, Tokenization *out) { case 'u': t.state = TokenizeState_char_literal_unicode_escape_saw_u; break; + case 'U': + invalid_char_error(&t, c); + break; default: t.state = TokenizeState_char_literal_end; break; @@ -785,7 +788,7 @@ void tokenize(const char *source, Tokenization *out) { break; case '}': if (seen_escape_digits == 0) { - tokenize_error(&t, "missing unicode escape sequence"); + tokenize_error(&t, "empty unicode escape sequence"); break; } t.state = TokenizeState_char_literal_end; diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 7e63460bfe..b2545d31f5 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -34,9 +34,9 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\ const c: *S = &.{}; \\} , &[_][]const u8{ - "mp.zig:2:31: error: expected type '[][]const u8', found '*const struct:2:31'", - "mp.zig:5:33: error: expected type '*[2][]const u8', found '*const struct:5:33'", - "mp.zig:9:21: error: expected type '*S', found '*const struct:9:21'", + "tmp.zig:2:31: error: expected type '[][]const u8', found '*const struct:2:31'", + "tmp.zig:5:33: error: expected type '*[2][]const u8', found '*const struct:5:33'", + "tmp.zig:9:21: error: expected type '*S', found '*const struct:9:21'", }); cases.add("@Type() union payload is undefined", @@ -8416,6 +8416,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\ var sequence = "repeat".*** 10; \\} , &[_][]const u8{ - "tmp.zig:2:30: error: `.*` can't be followed by `*`. Are you missing a space?", + "tmp.zig:2:30: error: `.*` cannot be followed by `*`. Are you missing a space?", }); } From f5d4fe3e17533f83404c16fbceff0dc7bb12cb18 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 28 May 2021 15:22:03 -0700 Subject: [PATCH 13/14] stage1: memoize strings in the AST Currently, stage1 runs astgen for every comptime function call, resulting in identifier strings being allocated multiple times, wasting memory. As a workaround until the code is adjusted to make astgen run only once per source node, we memoize the result into the AST. * Rename `ir_gen_*` to `astgen_*` - Oops, meant to do this in a separate commit. My bad. * tokenizer: avoid using designated initializer syntax. MSVC does not support it. --- src/stage1/all_types.hpp | 14 + src/stage1/astgen.cpp | 887 ++++++++++++++++++++------------------- src/stage1/parser.cpp | 43 +- src/stage1/parser.hpp | 2 - src/stage1/tokenizer.cpp | 10 +- 5 files changed, 489 insertions(+), 467 deletions(-) diff --git a/src/stage1/all_types.hpp b/src/stage1/all_types.hpp index 3af41c5788..27a609a1e4 100644 --- a/src/stage1/all_types.hpp +++ b/src/stage1/all_types.hpp @@ -1123,6 +1123,14 @@ struct AstNodeContainerInitExpr { ContainerInitKind kind; }; +struct AstNodeIdentifier { + Buf *name; +}; + +struct AstNodeEnumLiteral { + Buf *name; +}; + struct AstNodeBoolLiteral { bool value; }; @@ -1204,6 +1212,12 @@ struct AstNode { AstNodeAwaitExpr await_expr; AstNodeSuspend suspend; AstNodeAnyFrameType anyframe_type; + + // These are part of an astgen workaround to use less memory by + // memoizing into the AST. Once astgen is modified to only run once + // per corresponding source, this workaround can be removed. + AstNodeIdentifier identifier; + AstNodeEnumLiteral enum_literal; } data; // This is a function for use in the debugger to print diff --git a/src/stage1/astgen.cpp b/src/stage1/astgen.cpp index d7ec91f466..6f38eca936 100644 --- a/src/stage1/astgen.cpp +++ b/src/stage1/astgen.cpp @@ -21,15 +21,15 @@ struct Stage1AstGen { bool in_c_import_scope; }; -static IrInstSrc *ir_gen_node(Stage1AstGen *ag, AstNode *node, Scope *scope); -static IrInstSrc *ir_gen_node_extra(Stage1AstGen *ag, AstNode *node, Scope *scope, LVal lval, +static IrInstSrc *astgen_node(Stage1AstGen *ag, AstNode *node, Scope *scope); +static IrInstSrc *astgen_node_extra(Stage1AstGen *ag, AstNode *node, Scope *scope, LVal lval, ResultLoc *result_loc); static IrInstSrc *ir_lval_wrap(Stage1AstGen *ag, Scope *scope, IrInstSrc *value, LVal lval, ResultLoc *result_loc); static IrInstSrc *ir_expr_wrap(Stage1AstGen *ag, Scope *scope, IrInstSrc *inst, ResultLoc *result_loc); -static IrInstSrc *ir_gen_union_init_expr(Stage1AstGen *ag, Scope *scope, AstNode *source_node, +static IrInstSrc *astgen_union_init_expr(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *union_type, IrInstSrc *field_name, AstNode *expr_node, LVal lval, ResultLoc *parent_result_loc); static ResultLocCast *ir_build_cast_result_loc(Stage1AstGen *ag, IrInstSrc *dest_type, @@ -2890,7 +2890,7 @@ static IrInstSrc *ir_mark_gen(IrInstSrc *instruction) { return instruction; } -static bool ir_gen_defers_for_block(Stage1AstGen *ag, Scope *inner_scope, Scope *outer_scope, bool *is_noreturn, IrInstSrc *err_value) { +static bool astgen_defers_for_block(Stage1AstGen *ag, Scope *inner_scope, Scope *outer_scope, bool *is_noreturn, IrInstSrc *err_value) { Scope *scope = inner_scope; if (is_noreturn != nullptr) *is_noreturn = false; while (scope != outer_scope) { @@ -2941,7 +2941,7 @@ static bool ir_gen_defers_for_block(Stage1AstGen *ag, Scope *inner_scope, Scope defer_expr_scope = err_var->child_scope; } - IrInstSrc *defer_expr_value = ir_gen_node(ag, defer_expr_node, defer_expr_scope); + IrInstSrc *defer_expr_value = astgen_node(ag, defer_expr_node, defer_expr_scope); if (defer_expr_value == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; @@ -3011,7 +3011,7 @@ static ScopeDeferExpr *get_scope_defer_expr(Scope *scope) { return nullptr; } -static IrInstSrc *ir_gen_return(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { +static IrInstSrc *astgen_return(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypeReturnExpr); ScopeDeferExpr *scope_defer_expr = get_scope_defer_expr(scope); @@ -3038,7 +3038,7 @@ static IrInstSrc *ir_gen_return(Stage1AstGen *ag, Scope *scope, AstNode *node, L // Temporarily set this so that if we return a type it gets the name of the function ZigFn *prev_name_fn = ag->exec->name_fn; ag->exec->name_fn = ag->fn; - return_value = ir_gen_node_extra(ag, expr_node, scope, LValNone, &result_loc_ret->base); + return_value = astgen_node_extra(ag, expr_node, scope, LValNone, &result_loc_ret->base); ag->exec->name_fn = prev_name_fn; if (return_value == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; @@ -3054,7 +3054,7 @@ static IrInstSrc *ir_gen_return(Stage1AstGen *ag, Scope *scope, AstNode *node, L bool have_err_defers = defer_counts[ReturnKindError] > 0; if (!have_err_defers && !ag->codegen->have_err_ret_tracing) { // only generate unconditional defers - if (!ir_gen_defers_for_block(ag, scope, outer_scope, nullptr, nullptr)) + if (!astgen_defers_for_block(ag, scope, outer_scope, nullptr, nullptr)) return ag->codegen->invalid_inst_src; IrInstSrc *result = ir_build_return_src(ag, scope, node, nullptr); result_loc_ret->base.source_instruction = result; @@ -3078,7 +3078,7 @@ static IrInstSrc *ir_gen_return(Stage1AstGen *ag, Scope *scope, AstNode *node, L Stage1ZirBasicBlock *ret_stmt_block = ir_create_basic_block(ag, scope, "RetStmt"); ir_set_cursor_at_end_and_append_block(ag, err_block); - if (!ir_gen_defers_for_block(ag, scope, outer_scope, nullptr, return_value)) + if (!astgen_defers_for_block(ag, scope, outer_scope, nullptr, return_value)) return ag->codegen->invalid_inst_src; if (ag->codegen->have_err_ret_tracing && !should_inline) { ir_build_save_err_ret_addr_src(ag, scope, node); @@ -3086,7 +3086,7 @@ static IrInstSrc *ir_gen_return(Stage1AstGen *ag, Scope *scope, AstNode *node, L ir_build_br(ag, scope, node, ret_stmt_block, is_comptime); ir_set_cursor_at_end_and_append_block(ag, ok_block); - if (!ir_gen_defers_for_block(ag, scope, outer_scope, nullptr, nullptr)) + if (!astgen_defers_for_block(ag, scope, outer_scope, nullptr, nullptr)) return ag->codegen->invalid_inst_src; ir_build_br(ag, scope, node, ret_stmt_block, is_comptime); @@ -3098,7 +3098,7 @@ static IrInstSrc *ir_gen_return(Stage1AstGen *ag, Scope *scope, AstNode *node, L case ReturnKindError: { assert(expr_node); - IrInstSrc *err_union_ptr = ir_gen_node_extra(ag, expr_node, scope, LValPtr, nullptr); + IrInstSrc *err_union_ptr = astgen_node_extra(ag, expr_node, scope, LValPtr, nullptr); if (err_union_ptr == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; IrInstSrc *is_err_val = ir_build_test_err_src(ag, scope, node, err_union_ptr, true, false); @@ -3126,7 +3126,7 @@ static IrInstSrc *ir_gen_return(Stage1AstGen *ag, Scope *scope, AstNode *node, L ir_build_end_expr(ag, scope, node, err_val, &result_loc_ret->base); bool is_noreturn = false; - if (!ir_gen_defers_for_block(ag, scope, outer_scope, &is_noreturn, err_val)) { + if (!astgen_defers_for_block(ag, scope, outer_scope, &is_noreturn, err_val)) { return ag->codegen->invalid_inst_src; } if (!is_noreturn) { @@ -3260,7 +3260,7 @@ static bool is_duplicate_label(CodeGen *g, Scope *scope, AstNode *node, Buf *nam return false; } -static IrInstSrc *ir_gen_block(Stage1AstGen *ag, Scope *parent_scope, AstNode *block_node, LVal lval, +static IrInstSrc *astgen_block(Stage1AstGen *ag, Scope *parent_scope, AstNode *block_node, LVal lval, ResultLoc *result_loc) { assert(block_node->type == NodeTypeBlock); @@ -3313,7 +3313,7 @@ static IrInstSrc *ir_gen_block(Stage1AstGen *ag, Scope *parent_scope, AstNode *b for (size_t i = 0; i < block_node->data.block.statements.length; i += 1) { AstNode *statement_node = block_node->data.block.statements.at(i); - IrInstSrc *statement_value = ir_gen_node(ag, statement_node, child_scope); + IrInstSrc *statement_value = astgen_node(ag, statement_node, child_scope); if (statement_value == ag->codegen->invalid_inst_src) { // keep generating all the elements of the block in case of error, // we want to collect other compile errors @@ -3381,7 +3381,7 @@ static IrInstSrc *ir_gen_block(Stage1AstGen *ag, Scope *parent_scope, AstNode *b bool is_return_from_fn = block_node == ag->main_block_node; if (!is_return_from_fn) { - if (!ir_gen_defers_for_block(ag, child_scope, outer_block_scope, nullptr, nullptr)) + if (!astgen_defers_for_block(ag, child_scope, outer_block_scope, nullptr, nullptr)) return ag->codegen->invalid_inst_src; } @@ -3407,19 +3407,19 @@ static IrInstSrc *ir_gen_block(Stage1AstGen *ag, Scope *parent_scope, AstNode *b result_loc_ret->base.id = ResultLocIdReturn; ir_build_reset_result(ag, parent_scope, block_node, &result_loc_ret->base); ir_mark_gen(ir_build_end_expr(ag, parent_scope, block_node, result, &result_loc_ret->base)); - if (!ir_gen_defers_for_block(ag, child_scope, outer_block_scope, nullptr, nullptr)) + if (!astgen_defers_for_block(ag, child_scope, outer_block_scope, nullptr, nullptr)) return ag->codegen->invalid_inst_src; return ir_mark_gen(ir_build_return_src(ag, child_scope, result->base.source_node, result)); } -static IrInstSrc *ir_gen_bin_op_id(Stage1AstGen *ag, Scope *scope, AstNode *node, IrBinOp op_id) { +static IrInstSrc *astgen_bin_op_id(Stage1AstGen *ag, Scope *scope, AstNode *node, IrBinOp op_id) { Scope *inner_scope = scope; if (op_id == IrBinOpArrayCat || op_id == IrBinOpArrayMult) { inner_scope = create_comptime_scope(ag->codegen, node, scope); } - IrInstSrc *op1 = ir_gen_node(ag, node->data.bin_op_expr.op1, inner_scope); - IrInstSrc *op2 = ir_gen_node(ag, node->data.bin_op_expr.op2, inner_scope); + IrInstSrc *op1 = astgen_node(ag, node->data.bin_op_expr.op1, inner_scope); + IrInstSrc *op2 = astgen_node(ag, node->data.bin_op_expr.op2, inner_scope); if (op1 == ag->codegen->invalid_inst_src || op2 == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; @@ -3427,9 +3427,9 @@ static IrInstSrc *ir_gen_bin_op_id(Stage1AstGen *ag, Scope *scope, AstNode *node return ir_build_bin_op(ag, scope, node, op_id, op1, op2, true); } -static IrInstSrc *ir_gen_merge_err_sets(Stage1AstGen *ag, Scope *scope, AstNode *node) { - IrInstSrc *op1 = ir_gen_node(ag, node->data.bin_op_expr.op1, scope); - IrInstSrc *op2 = ir_gen_node(ag, node->data.bin_op_expr.op2, scope); +static IrInstSrc *astgen_merge_err_sets(Stage1AstGen *ag, Scope *scope, AstNode *node) { + IrInstSrc *op1 = astgen_node(ag, node->data.bin_op_expr.op1, scope); + IrInstSrc *op2 = astgen_node(ag, node->data.bin_op_expr.op2, scope); if (op1 == ag->codegen->invalid_inst_src || op2 == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; @@ -3441,8 +3441,8 @@ static IrInstSrc *ir_gen_merge_err_sets(Stage1AstGen *ag, Scope *scope, AstNode return ir_build_merge_err_sets(ag, scope, node, op1, op2, type_name); } -static IrInstSrc *ir_gen_assign(Stage1AstGen *ag, Scope *scope, AstNode *node) { - IrInstSrc *lvalue = ir_gen_node_extra(ag, node->data.bin_op_expr.op1, scope, LValAssign, nullptr); +static IrInstSrc *astgen_assign(Stage1AstGen *ag, Scope *scope, AstNode *node) { + IrInstSrc *lvalue = astgen_node_extra(ag, node->data.bin_op_expr.op1, scope, LValAssign, nullptr); if (lvalue == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; @@ -3452,7 +3452,7 @@ static IrInstSrc *ir_gen_assign(Stage1AstGen *ag, Scope *scope, AstNode *node) { ir_ref_instruction(lvalue, ag->current_basic_block); ir_build_reset_result(ag, scope, node, &result_loc_inst->base); - IrInstSrc *rvalue = ir_gen_node_extra(ag, node->data.bin_op_expr.op2, scope, LValNone, + IrInstSrc *rvalue = astgen_node_extra(ag, node->data.bin_op_expr.op2, scope, LValNone, &result_loc_inst->base); if (rvalue == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; @@ -3460,12 +3460,12 @@ static IrInstSrc *ir_gen_assign(Stage1AstGen *ag, Scope *scope, AstNode *node) { return ir_build_const_void(ag, scope, node); } -static IrInstSrc *ir_gen_assign_op(Stage1AstGen *ag, Scope *scope, AstNode *node, IrBinOp op_id) { - IrInstSrc *lvalue = ir_gen_node_extra(ag, node->data.bin_op_expr.op1, scope, LValAssign, nullptr); +static IrInstSrc *astgen_assign_op(Stage1AstGen *ag, Scope *scope, AstNode *node, IrBinOp op_id) { + IrInstSrc *lvalue = astgen_node_extra(ag, node->data.bin_op_expr.op1, scope, LValAssign, nullptr); if (lvalue == ag->codegen->invalid_inst_src) return lvalue; IrInstSrc *op1 = ir_build_load_ptr(ag, scope, node->data.bin_op_expr.op1, lvalue); - IrInstSrc *op2 = ir_gen_node(ag, node->data.bin_op_expr.op2, scope); + IrInstSrc *op2 = astgen_node(ag, node->data.bin_op_expr.op2, scope); if (op2 == ag->codegen->invalid_inst_src) return op2; IrInstSrc *result = ir_build_bin_op(ag, scope, node, op_id, op1, op2, true); @@ -3473,10 +3473,10 @@ static IrInstSrc *ir_gen_assign_op(Stage1AstGen *ag, Scope *scope, AstNode *node return ir_build_const_void(ag, scope, node); } -static IrInstSrc *ir_gen_bool_or(Stage1AstGen *ag, Scope *scope, AstNode *node) { +static IrInstSrc *astgen_bool_or(Stage1AstGen *ag, Scope *scope, AstNode *node) { assert(node->type == NodeTypeBinOpExpr); - IrInstSrc *val1 = ir_gen_node(ag, node->data.bin_op_expr.op1, scope); + IrInstSrc *val1 = astgen_node(ag, node->data.bin_op_expr.op1, scope); if (val1 == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; Stage1ZirBasicBlock *post_val1_block = ag->current_basic_block; @@ -3496,7 +3496,7 @@ static IrInstSrc *ir_gen_bool_or(Stage1AstGen *ag, Scope *scope, AstNode *node) ir_build_cond_br(ag, scope, node, val1, true_block, false_block, is_comptime); ir_set_cursor_at_end_and_append_block(ag, false_block); - IrInstSrc *val2 = ir_gen_node(ag, node->data.bin_op_expr.op2, scope); + IrInstSrc *val2 = astgen_node(ag, node->data.bin_op_expr.op2, scope); if (val2 == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; Stage1ZirBasicBlock *post_val2_block = ag->current_basic_block; @@ -3515,10 +3515,10 @@ static IrInstSrc *ir_gen_bool_or(Stage1AstGen *ag, Scope *scope, AstNode *node) return ir_build_phi(ag, scope, node, 2, incoming_blocks, incoming_values, nullptr); } -static IrInstSrc *ir_gen_bool_and(Stage1AstGen *ag, Scope *scope, AstNode *node) { +static IrInstSrc *astgen_bool_and(Stage1AstGen *ag, Scope *scope, AstNode *node) { assert(node->type == NodeTypeBinOpExpr); - IrInstSrc *val1 = ir_gen_node(ag, node->data.bin_op_expr.op1, scope); + IrInstSrc *val1 = astgen_node(ag, node->data.bin_op_expr.op1, scope); if (val1 == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; Stage1ZirBasicBlock *post_val1_block = ag->current_basic_block; @@ -3538,7 +3538,7 @@ static IrInstSrc *ir_gen_bool_and(Stage1AstGen *ag, Scope *scope, AstNode *node) ir_build_cond_br(ag, scope, node, val1, true_block, false_block, is_comptime); ir_set_cursor_at_end_and_append_block(ag, true_block); - IrInstSrc *val2 = ir_gen_node(ag, node->data.bin_op_expr.op2, scope); + IrInstSrc *val2 = astgen_node(ag, node->data.bin_op_expr.op2, scope); if (val2 == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; Stage1ZirBasicBlock *post_val2_block = ag->current_basic_block; @@ -3591,7 +3591,7 @@ static ResultLocPeerParent *ir_build_binary_result_peers(Stage1AstGen *ag, IrIns return peer_parent; } -static IrInstSrc *ir_gen_orelse(Stage1AstGen *ag, Scope *parent_scope, AstNode *node, LVal lval, +static IrInstSrc *astgen_orelse(Stage1AstGen *ag, Scope *parent_scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypeBinOpExpr); @@ -3599,7 +3599,7 @@ static IrInstSrc *ir_gen_orelse(Stage1AstGen *ag, Scope *parent_scope, AstNode * AstNode *op1_node = node->data.bin_op_expr.op1; AstNode *op2_node = node->data.bin_op_expr.op2; - IrInstSrc *maybe_ptr = ir_gen_node_extra(ag, op1_node, parent_scope, LValPtr, nullptr); + IrInstSrc *maybe_ptr = astgen_node_extra(ag, op1_node, parent_scope, LValPtr, nullptr); if (maybe_ptr == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; @@ -3622,7 +3622,7 @@ static IrInstSrc *ir_gen_orelse(Stage1AstGen *ag, Scope *parent_scope, AstNode * result_loc, is_comptime); ir_set_cursor_at_end_and_append_block(ag, null_block); - IrInstSrc *null_result = ir_gen_node_extra(ag, op2_node, parent_scope, LValNone, + IrInstSrc *null_result = astgen_node_extra(ag, op2_node, parent_scope, LValNone, &peer_parent->peers.at(0)->base); if (null_result == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; @@ -3648,24 +3648,24 @@ static IrInstSrc *ir_gen_orelse(Stage1AstGen *ag, Scope *parent_scope, AstNode * return ir_lval_wrap(ag, parent_scope, phi, lval, result_loc); } -static IrInstSrc *ir_gen_error_union(Stage1AstGen *ag, Scope *parent_scope, AstNode *node) { +static IrInstSrc *astgen_error_union(Stage1AstGen *ag, Scope *parent_scope, AstNode *node) { assert(node->type == NodeTypeBinOpExpr); AstNode *op1_node = node->data.bin_op_expr.op1; AstNode *op2_node = node->data.bin_op_expr.op2; - IrInstSrc *err_set = ir_gen_node(ag, op1_node, parent_scope); + IrInstSrc *err_set = astgen_node(ag, op1_node, parent_scope); if (err_set == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; - IrInstSrc *payload = ir_gen_node(ag, op2_node, parent_scope); + IrInstSrc *payload = astgen_node(ag, op2_node, parent_scope); if (payload == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; return ir_build_error_union(ag, parent_scope, node, err_set, payload); } -static IrInstSrc *ir_gen_bin_op(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { +static IrInstSrc *astgen_bin_op(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypeBinOpExpr); BinOpType bin_op_type = node->data.bin_op_expr.bin_op; @@ -3673,90 +3673,90 @@ static IrInstSrc *ir_gen_bin_op(Stage1AstGen *ag, Scope *scope, AstNode *node, L case BinOpTypeInvalid: zig_unreachable(); case BinOpTypeAssign: - return ir_lval_wrap(ag, scope, ir_gen_assign(ag, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_assign(ag, scope, node), lval, result_loc); case BinOpTypeAssignTimes: - return ir_lval_wrap(ag, scope, ir_gen_assign_op(ag, scope, node, IrBinOpMult), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_assign_op(ag, scope, node, IrBinOpMult), lval, result_loc); case BinOpTypeAssignTimesWrap: - return ir_lval_wrap(ag, scope, ir_gen_assign_op(ag, scope, node, IrBinOpMultWrap), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_assign_op(ag, scope, node, IrBinOpMultWrap), lval, result_loc); case BinOpTypeAssignDiv: - return ir_lval_wrap(ag, scope, ir_gen_assign_op(ag, scope, node, IrBinOpDivUnspecified), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_assign_op(ag, scope, node, IrBinOpDivUnspecified), lval, result_loc); case BinOpTypeAssignMod: - return ir_lval_wrap(ag, scope, ir_gen_assign_op(ag, scope, node, IrBinOpRemUnspecified), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_assign_op(ag, scope, node, IrBinOpRemUnspecified), lval, result_loc); case BinOpTypeAssignPlus: - return ir_lval_wrap(ag, scope, ir_gen_assign_op(ag, scope, node, IrBinOpAdd), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_assign_op(ag, scope, node, IrBinOpAdd), lval, result_loc); case BinOpTypeAssignPlusWrap: - return ir_lval_wrap(ag, scope, ir_gen_assign_op(ag, scope, node, IrBinOpAddWrap), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_assign_op(ag, scope, node, IrBinOpAddWrap), lval, result_loc); case BinOpTypeAssignMinus: - return ir_lval_wrap(ag, scope, ir_gen_assign_op(ag, scope, node, IrBinOpSub), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_assign_op(ag, scope, node, IrBinOpSub), lval, result_loc); case BinOpTypeAssignMinusWrap: - return ir_lval_wrap(ag, scope, ir_gen_assign_op(ag, scope, node, IrBinOpSubWrap), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_assign_op(ag, scope, node, IrBinOpSubWrap), lval, result_loc); case BinOpTypeAssignBitShiftLeft: - return ir_lval_wrap(ag, scope, ir_gen_assign_op(ag, scope, node, IrBinOpBitShiftLeftLossy), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_assign_op(ag, scope, node, IrBinOpBitShiftLeftLossy), lval, result_loc); case BinOpTypeAssignBitShiftRight: - return ir_lval_wrap(ag, scope, ir_gen_assign_op(ag, scope, node, IrBinOpBitShiftRightLossy), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_assign_op(ag, scope, node, IrBinOpBitShiftRightLossy), lval, result_loc); case BinOpTypeAssignBitAnd: - return ir_lval_wrap(ag, scope, ir_gen_assign_op(ag, scope, node, IrBinOpBinAnd), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_assign_op(ag, scope, node, IrBinOpBinAnd), lval, result_loc); case BinOpTypeAssignBitXor: - return ir_lval_wrap(ag, scope, ir_gen_assign_op(ag, scope, node, IrBinOpBinXor), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_assign_op(ag, scope, node, IrBinOpBinXor), lval, result_loc); case BinOpTypeAssignBitOr: - return ir_lval_wrap(ag, scope, ir_gen_assign_op(ag, scope, node, IrBinOpBinOr), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_assign_op(ag, scope, node, IrBinOpBinOr), lval, result_loc); case BinOpTypeBoolOr: - return ir_lval_wrap(ag, scope, ir_gen_bool_or(ag, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_bool_or(ag, scope, node), lval, result_loc); case BinOpTypeBoolAnd: - return ir_lval_wrap(ag, scope, ir_gen_bool_and(ag, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_bool_and(ag, scope, node), lval, result_loc); case BinOpTypeCmpEq: - return ir_lval_wrap(ag, scope, ir_gen_bin_op_id(ag, scope, node, IrBinOpCmpEq), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpCmpEq), lval, result_loc); case BinOpTypeCmpNotEq: - return ir_lval_wrap(ag, scope, ir_gen_bin_op_id(ag, scope, node, IrBinOpCmpNotEq), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpCmpNotEq), lval, result_loc); case BinOpTypeCmpLessThan: - return ir_lval_wrap(ag, scope, ir_gen_bin_op_id(ag, scope, node, IrBinOpCmpLessThan), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpCmpLessThan), lval, result_loc); case BinOpTypeCmpGreaterThan: - return ir_lval_wrap(ag, scope, ir_gen_bin_op_id(ag, scope, node, IrBinOpCmpGreaterThan), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpCmpGreaterThan), lval, result_loc); case BinOpTypeCmpLessOrEq: - return ir_lval_wrap(ag, scope, ir_gen_bin_op_id(ag, scope, node, IrBinOpCmpLessOrEq), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpCmpLessOrEq), lval, result_loc); case BinOpTypeCmpGreaterOrEq: - return ir_lval_wrap(ag, scope, ir_gen_bin_op_id(ag, scope, node, IrBinOpCmpGreaterOrEq), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpCmpGreaterOrEq), lval, result_loc); case BinOpTypeBinOr: - return ir_lval_wrap(ag, scope, ir_gen_bin_op_id(ag, scope, node, IrBinOpBinOr), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpBinOr), lval, result_loc); case BinOpTypeBinXor: - return ir_lval_wrap(ag, scope, ir_gen_bin_op_id(ag, scope, node, IrBinOpBinXor), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpBinXor), lval, result_loc); case BinOpTypeBinAnd: - return ir_lval_wrap(ag, scope, ir_gen_bin_op_id(ag, scope, node, IrBinOpBinAnd), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpBinAnd), lval, result_loc); case BinOpTypeBitShiftLeft: - return ir_lval_wrap(ag, scope, ir_gen_bin_op_id(ag, scope, node, IrBinOpBitShiftLeftLossy), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpBitShiftLeftLossy), lval, result_loc); case BinOpTypeBitShiftRight: - return ir_lval_wrap(ag, scope, ir_gen_bin_op_id(ag, scope, node, IrBinOpBitShiftRightLossy), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpBitShiftRightLossy), lval, result_loc); case BinOpTypeAdd: - return ir_lval_wrap(ag, scope, ir_gen_bin_op_id(ag, scope, node, IrBinOpAdd), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpAdd), lval, result_loc); case BinOpTypeAddWrap: - return ir_lval_wrap(ag, scope, ir_gen_bin_op_id(ag, scope, node, IrBinOpAddWrap), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpAddWrap), lval, result_loc); case BinOpTypeSub: - return ir_lval_wrap(ag, scope, ir_gen_bin_op_id(ag, scope, node, IrBinOpSub), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpSub), lval, result_loc); case BinOpTypeSubWrap: - return ir_lval_wrap(ag, scope, ir_gen_bin_op_id(ag, scope, node, IrBinOpSubWrap), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpSubWrap), lval, result_loc); case BinOpTypeMult: - return ir_lval_wrap(ag, scope, ir_gen_bin_op_id(ag, scope, node, IrBinOpMult), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpMult), lval, result_loc); case BinOpTypeMultWrap: - return ir_lval_wrap(ag, scope, ir_gen_bin_op_id(ag, scope, node, IrBinOpMultWrap), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpMultWrap), lval, result_loc); case BinOpTypeDiv: - return ir_lval_wrap(ag, scope, ir_gen_bin_op_id(ag, scope, node, IrBinOpDivUnspecified), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpDivUnspecified), lval, result_loc); case BinOpTypeMod: - return ir_lval_wrap(ag, scope, ir_gen_bin_op_id(ag, scope, node, IrBinOpRemUnspecified), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpRemUnspecified), lval, result_loc); case BinOpTypeArrayCat: - return ir_lval_wrap(ag, scope, ir_gen_bin_op_id(ag, scope, node, IrBinOpArrayCat), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpArrayCat), lval, result_loc); case BinOpTypeArrayMult: - return ir_lval_wrap(ag, scope, ir_gen_bin_op_id(ag, scope, node, IrBinOpArrayMult), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpArrayMult), lval, result_loc); case BinOpTypeMergeErrorSets: - return ir_lval_wrap(ag, scope, ir_gen_merge_err_sets(ag, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_merge_err_sets(ag, scope, node), lval, result_loc); case BinOpTypeUnwrapOptional: - return ir_gen_orelse(ag, scope, node, lval, result_loc); + return astgen_orelse(ag, scope, node, lval, result_loc); case BinOpTypeErrorUnion: - return ir_lval_wrap(ag, scope, ir_gen_error_union(ag, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_error_union(ag, scope, node), lval, result_loc); } zig_unreachable(); } -static IrInstSrc *ir_gen_int_lit(Stage1AstGen *ag, Scope *scope, AstNode *node) { +static IrInstSrc *astgen_int_lit(Stage1AstGen *ag, Scope *scope, AstNode *node) { assert(node->type == NodeTypeIntLiteral); RootStruct *root_struct = node->owner->data.structure.root_struct; @@ -3765,7 +3765,7 @@ static IrInstSrc *ir_gen_int_lit(Stage1AstGen *ag, Scope *scope, AstNode *node) return ir_build_const_bigint(ag, scope, node, bigint); } -static IrInstSrc *ir_gen_float_lit(Stage1AstGen *ag, Scope *scope, AstNode *node) { +static IrInstSrc *astgen_float_lit(Stage1AstGen *ag, Scope *scope, AstNode *node) { Error err; assert(node->type == NodeTypeFloatLiteral); @@ -3782,7 +3782,7 @@ static IrInstSrc *ir_gen_float_lit(Stage1AstGen *ag, Scope *scope, AstNode *node return ir_build_const_bigfloat(ag, scope, node, bigfloat); } -static IrInstSrc *ir_gen_char_lit(Stage1AstGen *ag, Scope *scope, AstNode *node) { +static IrInstSrc *astgen_char_lit(Stage1AstGen *ag, Scope *scope, AstNode *node) { Error err; assert(node->type == NodeTypeCharLiteral); @@ -3802,13 +3802,15 @@ static IrInstSrc *ir_gen_char_lit(Stage1AstGen *ag, Scope *scope, AstNode *node) return ir_build_const_uint(ag, scope, node, codepoint); } -static IrInstSrc *ir_gen_null_literal(Stage1AstGen *ag, Scope *scope, AstNode *node) { +static IrInstSrc *astgen_null_literal(Stage1AstGen *ag, Scope *scope, AstNode *node) { assert(node->type == NodeTypeNullLiteral); return ir_build_const_null(ag, scope, node); } -static IrInstSrc *ir_gen_symbol(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { +static IrInstSrc *astgen_identifier(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, + ResultLoc *result_loc) +{ Error err; assert(node->type == NodeTypeIdentifier); @@ -3877,13 +3879,13 @@ static IrInstSrc *ir_gen_symbol(Stage1AstGen *ag, Scope *scope, AstNode *node, L return ir_build_undeclared_identifier(ag, scope, node, variable_name); } -static IrInstSrc *ir_gen_array_access(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, +static IrInstSrc *astgen_array_access(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypeArrayAccessExpr); AstNode *array_ref_node = node->data.array_access_expr.array_ref_expr; - IrInstSrc *array_ref_instruction = ir_gen_node_extra(ag, array_ref_node, scope, LValPtr, nullptr); + IrInstSrc *array_ref_instruction = astgen_node_extra(ag, array_ref_node, scope, LValPtr, nullptr); if (array_ref_instruction == ag->codegen->invalid_inst_src) return array_ref_instruction; @@ -3894,7 +3896,7 @@ static IrInstSrc *ir_gen_array_access(Stage1AstGen *ag, Scope *scope, AstNode *n ResultLocCast *result_loc_cast = ir_build_cast_result_loc(ag, usize_type_inst, no_result_loc()); AstNode *subscript_node = node->data.array_access_expr.subscript; - IrInstSrc *subscript_value = ir_gen_node_extra(ag, subscript_node, scope, LValNone, &result_loc_cast->base); + IrInstSrc *subscript_value = astgen_node_extra(ag, subscript_node, scope, LValNone, &result_loc_cast->base); if (subscript_value == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; @@ -3909,20 +3911,20 @@ static IrInstSrc *ir_gen_array_access(Stage1AstGen *ag, Scope *scope, AstNode *n return ir_expr_wrap(ag, scope, load_ptr, result_loc); } -static IrInstSrc *ir_gen_field_access(Stage1AstGen *ag, Scope *scope, AstNode *node) { +static IrInstSrc *astgen_field_access(Stage1AstGen *ag, Scope *scope, AstNode *node) { assert(node->type == NodeTypeFieldAccessExpr); AstNode *container_ref_node = node->data.field_access_expr.struct_expr; Buf *field_name = node->data.field_access_expr.field_name; - IrInstSrc *container_ref_instruction = ir_gen_node_extra(ag, container_ref_node, scope, LValPtr, nullptr); + IrInstSrc *container_ref_instruction = astgen_node_extra(ag, container_ref_node, scope, LValPtr, nullptr); if (container_ref_instruction == ag->codegen->invalid_inst_src) return container_ref_instruction; return ir_build_field_ptr(ag, scope, node, container_ref_instruction, field_name, false); } -static IrInstSrc *ir_gen_overflow_op(Stage1AstGen *ag, Scope *scope, AstNode *node, IrOverflowOp op) { +static IrInstSrc *astgen_overflow_op(Stage1AstGen *ag, Scope *scope, AstNode *node, IrOverflowOp op) { assert(node->type == NodeTypeFnCallExpr); AstNode *type_node = node->data.fn_call_expr.params.at(0); @@ -3931,26 +3933,26 @@ static IrInstSrc *ir_gen_overflow_op(Stage1AstGen *ag, Scope *scope, AstNode *no AstNode *result_ptr_node = node->data.fn_call_expr.params.at(3); - IrInstSrc *type_value = ir_gen_node(ag, type_node, scope); + IrInstSrc *type_value = astgen_node(ag, type_node, scope); if (type_value == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; - IrInstSrc *op1 = ir_gen_node(ag, op1_node, scope); + IrInstSrc *op1 = astgen_node(ag, op1_node, scope); if (op1 == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; - IrInstSrc *op2 = ir_gen_node(ag, op2_node, scope); + IrInstSrc *op2 = astgen_node(ag, op2_node, scope); if (op2 == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; - IrInstSrc *result_ptr = ir_gen_node(ag, result_ptr_node, scope); + IrInstSrc *result_ptr = astgen_node(ag, result_ptr_node, scope); if (result_ptr == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; return ir_build_overflow_op_src(ag, scope, node, op, type_value, op1, op2, result_ptr); } -static IrInstSrc *ir_gen_mul_add(Stage1AstGen *ag, Scope *scope, AstNode *node) { +static IrInstSrc *astgen_mul_add(Stage1AstGen *ag, Scope *scope, AstNode *node) { assert(node->type == NodeTypeFnCallExpr); AstNode *type_node = node->data.fn_call_expr.params.at(0); @@ -3958,26 +3960,26 @@ static IrInstSrc *ir_gen_mul_add(Stage1AstGen *ag, Scope *scope, AstNode *node) AstNode *op2_node = node->data.fn_call_expr.params.at(2); AstNode *op3_node = node->data.fn_call_expr.params.at(3); - IrInstSrc *type_value = ir_gen_node(ag, type_node, scope); + IrInstSrc *type_value = astgen_node(ag, type_node, scope); if (type_value == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; - IrInstSrc *op1 = ir_gen_node(ag, op1_node, scope); + IrInstSrc *op1 = astgen_node(ag, op1_node, scope); if (op1 == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; - IrInstSrc *op2 = ir_gen_node(ag, op2_node, scope); + IrInstSrc *op2 = astgen_node(ag, op2_node, scope); if (op2 == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; - IrInstSrc *op3 = ir_gen_node(ag, op3_node, scope); + IrInstSrc *op3 = astgen_node(ag, op3_node, scope); if (op3 == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; return ir_build_mul_add_src(ag, scope, node, type_value, op1, op2, op3); } -static IrInstSrc *ir_gen_this(Stage1AstGen *ag, Scope *orig_scope, AstNode *node) { +static IrInstSrc *astgen_this(Stage1AstGen *ag, Scope *orig_scope, AstNode *node) { for (Scope *it_scope = orig_scope; it_scope != nullptr; it_scope = it_scope->parent) { if (it_scope->id == ScopeIdDecls) { ScopeDecls *decls_scope = (ScopeDecls *)it_scope; @@ -3992,7 +3994,7 @@ static IrInstSrc *ir_gen_this(Stage1AstGen *ag, Scope *orig_scope, AstNode *node zig_unreachable(); } -static IrInstSrc *ir_gen_async_call(Stage1AstGen *ag, Scope *scope, AstNode *await_node, AstNode *call_node, +static IrInstSrc *astgen_async_call(Stage1AstGen *ag, Scope *scope, AstNode *await_node, AstNode *call_node, LVal lval, ResultLoc *result_loc) { if (call_node->data.fn_call_expr.params.length != 4) { @@ -4003,17 +4005,17 @@ static IrInstSrc *ir_gen_async_call(Stage1AstGen *ag, Scope *scope, AstNode *awa } AstNode *bytes_node = call_node->data.fn_call_expr.params.at(0); - IrInstSrc *bytes = ir_gen_node(ag, bytes_node, scope); + IrInstSrc *bytes = astgen_node(ag, bytes_node, scope); if (bytes == ag->codegen->invalid_inst_src) return bytes; AstNode *ret_ptr_node = call_node->data.fn_call_expr.params.at(1); - IrInstSrc *ret_ptr = ir_gen_node(ag, ret_ptr_node, scope); + IrInstSrc *ret_ptr = astgen_node(ag, ret_ptr_node, scope); if (ret_ptr == ag->codegen->invalid_inst_src) return ret_ptr; AstNode *fn_ref_node = call_node->data.fn_call_expr.params.at(2); - IrInstSrc *fn_ref = ir_gen_node(ag, fn_ref_node, scope); + IrInstSrc *fn_ref = astgen_node(ag, fn_ref_node, scope); if (fn_ref == ag->codegen->invalid_inst_src) return fn_ref; @@ -4028,7 +4030,7 @@ static IrInstSrc *ir_gen_async_call(Stage1AstGen *ag, Scope *scope, AstNode *awa IrInstSrc **args = heap::c_allocator.allocate(arg_count); for (size_t i = 0; i < arg_count; i += 1) { AstNode *arg_node = args_node->data.container_init_expr.entries.at(i); - IrInstSrc *arg = ir_gen_node(ag, arg_node, scope); + IrInstSrc *arg = astgen_node(ag, arg_node, scope); if (arg == ag->codegen->invalid_inst_src) return arg; args[i] = arg; @@ -4043,7 +4045,7 @@ static IrInstSrc *ir_gen_async_call(Stage1AstGen *ag, Scope *scope, AstNode *awa return ag->codegen->invalid_inst_src; } } - IrInstSrc *args = ir_gen_node(ag, args_node, scope); + IrInstSrc *args = astgen_node(ag, args_node, scope); if (args == ag->codegen->invalid_inst_src) return args; @@ -4051,11 +4053,11 @@ static IrInstSrc *ir_gen_async_call(Stage1AstGen *ag, Scope *scope, AstNode *awa return ir_lval_wrap(ag, scope, call, lval, result_loc); } -static IrInstSrc *ir_gen_fn_call_with_args(Stage1AstGen *ag, Scope *scope, AstNode *source_node, +static IrInstSrc *astgen_fn_call_with_args(Stage1AstGen *ag, Scope *scope, AstNode *source_node, AstNode *fn_ref_node, CallModifier modifier, IrInstSrc *options, AstNode **args_ptr, size_t args_len, LVal lval, ResultLoc *result_loc) { - IrInstSrc *fn_ref = ir_gen_node(ag, fn_ref_node, scope); + IrInstSrc *fn_ref = astgen_node(ag, fn_ref_node, scope); if (fn_ref == ag->codegen->invalid_inst_src) return fn_ref; @@ -4071,7 +4073,7 @@ static IrInstSrc *ir_gen_fn_call_with_args(Stage1AstGen *ag, Scope *scope, AstNo ir_build_reset_result(ag, scope, source_node, no_result); ResultLocCast *result_loc_cast = ir_build_cast_result_loc(ag, arg_type, no_result); - IrInstSrc *arg = ir_gen_node_extra(ag, arg_node, scope, LValNone, &result_loc_cast->base); + IrInstSrc *arg = astgen_node_extra(ag, arg_node, scope, LValNone, &result_loc_cast->base); if (arg == ag->codegen->invalid_inst_src) return arg; @@ -4088,7 +4090,7 @@ static IrInstSrc *ir_gen_fn_call_with_args(Stage1AstGen *ag, Scope *scope, AstNo return ir_lval_wrap(ag, scope, fn_call, lval, result_loc); } -static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, +static IrInstSrc *astgen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypeFnCallExpr); @@ -4130,7 +4132,7 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode return ag->codegen->invalid_inst_src; } else if (arg_count == 1) { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, sub_scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, sub_scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; @@ -4139,7 +4141,7 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode IrInstSrc **args = heap::c_allocator.allocate(arg_count); for (size_t i = 0; i < arg_count; i += 1) { AstNode *arg_node = node->data.fn_call_expr.params.at(i); - IrInstSrc *arg = ir_gen_node(ag, arg_node, sub_scope); + IrInstSrc *arg = astgen_node(ag, arg_node, sub_scope); if (arg == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; args[i] = arg; @@ -4152,7 +4154,7 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdSetCold: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; @@ -4162,7 +4164,7 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdSetRuntimeSafety: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; @@ -4172,7 +4174,7 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdSetFloatMode: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; @@ -4183,7 +4185,7 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdBitSizeof: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; @@ -4193,7 +4195,7 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdImport: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; @@ -4208,7 +4210,7 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdCInclude: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; @@ -4223,12 +4225,12 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdCDefine: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; @@ -4243,7 +4245,7 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdCUndef: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; @@ -4258,7 +4260,7 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdCompileErr: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; @@ -4271,7 +4273,7 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode for (size_t i = 0; i < actual_param_count; i += 1) { AstNode *arg_node = node->data.fn_call_expr.params.at(i); - args[i] = ir_gen_node(ag, arg_node, scope); + args[i] = astgen_node(ag, arg_node, scope); if (args[i] == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; } @@ -4282,7 +4284,7 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdErrName: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; @@ -4292,7 +4294,7 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdEmbedFile: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; @@ -4303,32 +4305,32 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdCmpxchgStrong: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; AstNode *arg2_node = node->data.fn_call_expr.params.at(2); - IrInstSrc *arg2_value = ir_gen_node(ag, arg2_node, scope); + IrInstSrc *arg2_value = astgen_node(ag, arg2_node, scope); if (arg2_value == ag->codegen->invalid_inst_src) return arg2_value; AstNode *arg3_node = node->data.fn_call_expr.params.at(3); - IrInstSrc *arg3_value = ir_gen_node(ag, arg3_node, scope); + IrInstSrc *arg3_value = astgen_node(ag, arg3_node, scope); if (arg3_value == ag->codegen->invalid_inst_src) return arg3_value; AstNode *arg4_node = node->data.fn_call_expr.params.at(4); - IrInstSrc *arg4_value = ir_gen_node(ag, arg4_node, scope); + IrInstSrc *arg4_value = astgen_node(ag, arg4_node, scope); if (arg4_value == ag->codegen->invalid_inst_src) return arg4_value; AstNode *arg5_node = node->data.fn_call_expr.params.at(5); - IrInstSrc *arg5_value = ir_gen_node(ag, arg5_node, scope); + IrInstSrc *arg5_value = astgen_node(ag, arg5_node, scope); if (arg5_value == ag->codegen->invalid_inst_src) return arg5_value; @@ -4340,7 +4342,7 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdFence: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; @@ -4350,12 +4352,12 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdReduce: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; @@ -4365,12 +4367,12 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdDivExact: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; @@ -4380,12 +4382,12 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdDivTrunc: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; @@ -4395,12 +4397,12 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdDivFloor: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; @@ -4410,12 +4412,12 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdRem: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; @@ -4425,12 +4427,12 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdMod: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; @@ -4453,7 +4455,7 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdRound: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; @@ -4463,12 +4465,12 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdTruncate: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; @@ -4478,12 +4480,12 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdIntCast: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; @@ -4493,12 +4495,12 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdFloatCast: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; @@ -4508,12 +4510,12 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdErrSetCast: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; @@ -4523,12 +4525,12 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdIntToFloat: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; @@ -4538,12 +4540,12 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdFloatToInt: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; @@ -4553,7 +4555,7 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdErrToInt: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; @@ -4563,7 +4565,7 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdIntToErr: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; @@ -4573,7 +4575,7 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdBoolToInt: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; @@ -4583,12 +4585,12 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdVectorType: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; @@ -4598,22 +4600,22 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdShuffle: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; AstNode *arg2_node = node->data.fn_call_expr.params.at(2); - IrInstSrc *arg2_value = ir_gen_node(ag, arg2_node, scope); + IrInstSrc *arg2_value = astgen_node(ag, arg2_node, scope); if (arg2_value == ag->codegen->invalid_inst_src) return arg2_value; AstNode *arg3_node = node->data.fn_call_expr.params.at(3); - IrInstSrc *arg3_value = ir_gen_node(ag, arg3_node, scope); + IrInstSrc *arg3_value = astgen_node(ag, arg3_node, scope); if (arg3_value == ag->codegen->invalid_inst_src) return arg3_value; @@ -4624,12 +4626,12 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdSplat: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; @@ -4640,17 +4642,17 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdMemcpy: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; AstNode *arg2_node = node->data.fn_call_expr.params.at(2); - IrInstSrc *arg2_value = ir_gen_node(ag, arg2_node, scope); + IrInstSrc *arg2_value = astgen_node(ag, arg2_node, scope); if (arg2_value == ag->codegen->invalid_inst_src) return arg2_value; @@ -4660,17 +4662,17 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdMemset: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; AstNode *arg2_node = node->data.fn_call_expr.params.at(2); - IrInstSrc *arg2_value = ir_gen_node(ag, arg2_node, scope); + IrInstSrc *arg2_value = astgen_node(ag, arg2_node, scope); if (arg2_value == ag->codegen->invalid_inst_src) return arg2_value; @@ -4680,7 +4682,7 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdWasmMemorySize: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; @@ -4690,12 +4692,12 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdWasmMemoryGrow: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; @@ -4705,12 +4707,12 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdField: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node_extra(ag, arg0_node, scope, LValPtr, nullptr); + IrInstSrc *arg0_value = astgen_node_extra(ag, arg0_node, scope, LValPtr, nullptr); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; @@ -4726,12 +4728,12 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdHasField: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; @@ -4741,7 +4743,7 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdTypeInfo: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; @@ -4751,7 +4753,7 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdType: { AstNode *arg_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg = ir_gen_node(ag, arg_node, scope); + IrInstSrc *arg = astgen_node(ag, arg_node, scope); if (arg == ag->codegen->invalid_inst_src) return arg; @@ -4773,7 +4775,7 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode return ir_lval_wrap(ag, scope, ir_build_handle_src(ag, scope, node), lval, result_loc); case BuiltinFnIdFrameType: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; @@ -4782,7 +4784,7 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode } case BuiltinFnIdFrameSize: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; @@ -4792,7 +4794,7 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdAlignOf: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; @@ -4800,19 +4802,19 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode return ir_lval_wrap(ag, scope, align_of, lval, result_loc); } case BuiltinFnIdAddWithOverflow: - return ir_lval_wrap(ag, scope, ir_gen_overflow_op(ag, scope, node, IrOverflowOpAdd), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_overflow_op(ag, scope, node, IrOverflowOpAdd), lval, result_loc); case BuiltinFnIdSubWithOverflow: - return ir_lval_wrap(ag, scope, ir_gen_overflow_op(ag, scope, node, IrOverflowOpSub), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_overflow_op(ag, scope, node, IrOverflowOpSub), lval, result_loc); case BuiltinFnIdMulWithOverflow: - return ir_lval_wrap(ag, scope, ir_gen_overflow_op(ag, scope, node, IrOverflowOpMul), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_overflow_op(ag, scope, node, IrOverflowOpMul), lval, result_loc); case BuiltinFnIdShlWithOverflow: - return ir_lval_wrap(ag, scope, ir_gen_overflow_op(ag, scope, node, IrOverflowOpShl), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_overflow_op(ag, scope, node, IrOverflowOpShl), lval, result_loc); case BuiltinFnIdMulAdd: - return ir_lval_wrap(ag, scope, ir_gen_mul_add(ag, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_mul_add(ag, scope, node), lval, result_loc); case BuiltinFnIdTypeName: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; @@ -4822,7 +4824,7 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdPanic: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; @@ -4832,12 +4834,12 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdPtrCast: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; @@ -4847,7 +4849,7 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdBitCast: { AstNode *dest_type_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *dest_type = ir_gen_node(ag, dest_type_node, scope); + IrInstSrc *dest_type = astgen_node(ag, dest_type_node, scope); if (dest_type == ag->codegen->invalid_inst_src) return dest_type; @@ -4861,7 +4863,7 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode ir_build_reset_result(ag, scope, node, &result_loc_bit_cast->base); AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node_extra(ag, arg1_node, scope, LValNone, + IrInstSrc *arg1_value = astgen_node_extra(ag, arg1_node, scope, LValNone, &result_loc_bit_cast->base); if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; @@ -4872,14 +4874,14 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdAs: { AstNode *dest_type_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *dest_type = ir_gen_node(ag, dest_type_node, scope); + IrInstSrc *dest_type = astgen_node(ag, dest_type_node, scope); if (dest_type == ag->codegen->invalid_inst_src) return dest_type; ResultLocCast *result_loc_cast = ir_build_cast_result_loc(ag, dest_type, result_loc); AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node_extra(ag, arg1_node, scope, LValNone, + IrInstSrc *arg1_value = astgen_node_extra(ag, arg1_node, scope, LValNone, &result_loc_cast->base); if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; @@ -4890,12 +4892,12 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdIntToPtr: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; @@ -4905,7 +4907,7 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdPtrToInt: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; @@ -4915,7 +4917,7 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdTagName: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; @@ -4925,17 +4927,17 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdFieldParentPtr: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; AstNode *arg2_node = node->data.fn_call_expr.params.at(2); - IrInstSrc *arg2_value = ir_gen_node(ag, arg2_node, scope); + IrInstSrc *arg2_value = astgen_node(ag, arg2_node, scope); if (arg2_value == ag->codegen->invalid_inst_src) return arg2_value; @@ -4946,12 +4948,12 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdByteOffsetOf: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; @@ -4961,12 +4963,12 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdBitOffsetOf: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; @@ -4980,7 +4982,7 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode ResultLocCast *result_loc_cast = ir_build_cast_result_loc(ag, options_type_inst, no_result_loc()); AstNode *options_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *options_inner = ir_gen_node_extra(ag, options_node, scope, + IrInstSrc *options_inner = astgen_node_extra(ag, options_node, scope, LValNone, &result_loc_cast->base); if (options_inner == ag->codegen->invalid_inst_src) return options_inner; @@ -4992,7 +4994,7 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode if (args_node->data.container_init_expr.kind == ContainerInitKindArray || args_node->data.container_init_expr.entries.length == 0) { - return ir_gen_fn_call_with_args(ag, scope, node, + return astgen_fn_call_with_args(ag, scope, node, fn_ref_node, CallModifierNone, options, args_node->data.container_init_expr.entries.items, args_node->data.container_init_expr.entries.length, @@ -5003,11 +5005,11 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode return ag->codegen->invalid_inst_src; } } else { - IrInstSrc *fn_ref = ir_gen_node(ag, fn_ref_node, scope); + IrInstSrc *fn_ref = astgen_node(ag, fn_ref_node, scope); if (fn_ref == ag->codegen->invalid_inst_src) return fn_ref; - IrInstSrc *args = ir_gen_node(ag, args_node, scope); + IrInstSrc *args = astgen_node(ag, args_node, scope); if (args == ag->codegen->invalid_inst_src) return args; @@ -5016,16 +5018,16 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode } } case BuiltinFnIdAsyncCall: - return ir_gen_async_call(ag, scope, nullptr, node, lval, result_loc); + return astgen_async_call(ag, scope, nullptr, node, lval, result_loc); case BuiltinFnIdShlExact: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; @@ -5035,12 +5037,12 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdShrExact: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; @@ -5050,7 +5052,7 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdSetEvalBranchQuota: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; @@ -5060,12 +5062,12 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdAlignCast: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; @@ -5074,13 +5076,13 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode } case BuiltinFnIdThis: { - IrInstSrc *this_inst = ir_gen_this(ag, scope, node); + IrInstSrc *this_inst = astgen_this(ag, scope, node); return ir_lval_wrap(ag, scope, this_inst, lval, result_loc); } case BuiltinFnIdSetAlignStack: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; @@ -5095,12 +5097,12 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode ResultLocCast *result_loc_cast = ir_build_cast_result_loc(ag, options_type_inst, no_result_loc()); AstNode *target_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *target_value = ir_gen_node(ag, target_node, scope); + IrInstSrc *target_value = astgen_node(ag, target_node, scope); if (target_value == ag->codegen->invalid_inst_src) return target_value; AstNode *options_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *options_value = ir_gen_node_extra(ag, options_node, + IrInstSrc *options_value = astgen_node_extra(ag, options_node, scope, LValNone, &result_loc_cast->base); if (options_value == ag->codegen->invalid_inst_src) return options_value; @@ -5119,12 +5121,12 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode ResultLocCast *result_loc_cast = ir_build_cast_result_loc(ag, options_type_inst, no_result_loc()); AstNode *type_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *type_value = ir_gen_node(ag, type_node, scope); + IrInstSrc *type_value = astgen_node(ag, type_node, scope); if (type_value == ag->codegen->invalid_inst_src) return type_value; AstNode *options_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *options_value = ir_gen_node_extra(ag, options_node, + IrInstSrc *options_value = astgen_node_extra(ag, options_node, scope, LValNone, &result_loc_cast->base); if (options_value == ag->codegen->invalid_inst_src) return options_value; @@ -5144,27 +5146,27 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdAtomicRmw: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; AstNode *arg2_node = node->data.fn_call_expr.params.at(2); - IrInstSrc *arg2_value = ir_gen_node(ag, arg2_node, scope); + IrInstSrc *arg2_value = astgen_node(ag, arg2_node, scope); if (arg2_value == ag->codegen->invalid_inst_src) return arg2_value; AstNode *arg3_node = node->data.fn_call_expr.params.at(3); - IrInstSrc *arg3_value = ir_gen_node(ag, arg3_node, scope); + IrInstSrc *arg3_value = astgen_node(ag, arg3_node, scope); if (arg3_value == ag->codegen->invalid_inst_src) return arg3_value; AstNode *arg4_node = node->data.fn_call_expr.params.at(4); - IrInstSrc *arg4_value = ir_gen_node(ag, arg4_node, scope); + IrInstSrc *arg4_value = astgen_node(ag, arg4_node, scope); if (arg4_value == ag->codegen->invalid_inst_src) return arg4_value; @@ -5175,17 +5177,17 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdAtomicLoad: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; AstNode *arg2_node = node->data.fn_call_expr.params.at(2); - IrInstSrc *arg2_value = ir_gen_node(ag, arg2_node, scope); + IrInstSrc *arg2_value = astgen_node(ag, arg2_node, scope); if (arg2_value == ag->codegen->invalid_inst_src) return arg2_value; @@ -5195,22 +5197,22 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdAtomicStore: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; AstNode *arg2_node = node->data.fn_call_expr.params.at(2); - IrInstSrc *arg2_value = ir_gen_node(ag, arg2_node, scope); + IrInstSrc *arg2_value = astgen_node(ag, arg2_node, scope); if (arg2_value == ag->codegen->invalid_inst_src) return arg2_value; AstNode *arg3_node = node->data.fn_call_expr.params.at(3); - IrInstSrc *arg3_value = ir_gen_node(ag, arg3_node, scope); + IrInstSrc *arg3_value = astgen_node(ag, arg3_node, scope); if (arg3_value == ag->codegen->invalid_inst_src) return arg3_value; @@ -5221,12 +5223,12 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdIntToEnum: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; @@ -5236,7 +5238,7 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdEnumToInt: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; @@ -5250,12 +5252,12 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdBitReverse: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; @@ -5284,12 +5286,12 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdHasDecl: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(ag, arg0_node, scope); + IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); if (arg0_value == ag->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(ag, arg1_node, scope); + IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); if (arg1_value == ag->codegen->invalid_inst_src) return arg1_value; @@ -5299,18 +5301,18 @@ static IrInstSrc *ir_gen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode case BuiltinFnIdUnionInit: { AstNode *union_type_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *union_type_inst = ir_gen_node(ag, union_type_node, scope); + IrInstSrc *union_type_inst = astgen_node(ag, union_type_node, scope); if (union_type_inst == ag->codegen->invalid_inst_src) return union_type_inst; AstNode *name_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *name_inst = ir_gen_node(ag, name_node, scope); + IrInstSrc *name_inst = astgen_node(ag, name_node, scope); if (name_inst == ag->codegen->invalid_inst_src) return name_inst; AstNode *init_node = node->data.fn_call_expr.params.at(2); - return ir_gen_union_init_expr(ag, scope, node, union_type_inst, name_inst, init_node, + return astgen_union_init_expr(ag, scope, node, union_type_inst, name_inst, init_node, lval, result_loc); } case BuiltinFnIdSrc: @@ -5334,13 +5336,13 @@ static ScopeNoSuspend *get_scope_nosuspend(Scope *scope) { return nullptr; } -static IrInstSrc *ir_gen_fn_call(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, +static IrInstSrc *astgen_fn_call(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypeFnCallExpr); if (node->data.fn_call_expr.modifier == CallModifierBuiltin) - return ir_gen_builtin_fn_call(ag, scope, node, lval, result_loc); + return astgen_builtin_fn_call(ag, scope, node, lval, result_loc); bool is_nosuspend = get_scope_nosuspend(scope) != nullptr; CallModifier modifier = node->data.fn_call_expr.modifier; @@ -5349,16 +5351,16 @@ static IrInstSrc *ir_gen_fn_call(Stage1AstGen *ag, Scope *scope, AstNode *node, } AstNode *fn_ref_node = node->data.fn_call_expr.fn_ref_expr; - return ir_gen_fn_call_with_args(ag, scope, node, fn_ref_node, modifier, + return astgen_fn_call_with_args(ag, scope, node, fn_ref_node, modifier, nullptr, node->data.fn_call_expr.params.items, node->data.fn_call_expr.params.length, lval, result_loc); } -static IrInstSrc *ir_gen_if_bool_expr(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, +static IrInstSrc *astgen_if_bool_expr(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypeIfBoolExpr); - IrInstSrc *condition = ir_gen_node(ag, node->data.if_bool_expr.condition, scope); + IrInstSrc *condition = astgen_node(ag, node->data.if_bool_expr.condition, scope); if (condition == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; @@ -5384,7 +5386,7 @@ static IrInstSrc *ir_gen_if_bool_expr(Stage1AstGen *ag, Scope *scope, AstNode *n ir_set_cursor_at_end_and_append_block(ag, then_block); Scope *subexpr_scope = create_runtime_scope(ag->codegen, node, scope, is_comptime); - IrInstSrc *then_expr_result = ir_gen_node_extra(ag, then_node, subexpr_scope, lval, + IrInstSrc *then_expr_result = astgen_node_extra(ag, then_node, subexpr_scope, lval, &peer_parent->peers.at(0)->base); if (then_expr_result == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; @@ -5395,7 +5397,7 @@ static IrInstSrc *ir_gen_if_bool_expr(Stage1AstGen *ag, Scope *scope, AstNode *n ir_set_cursor_at_end_and_append_block(ag, else_block); IrInstSrc *else_expr_result; if (else_node) { - else_expr_result = ir_gen_node_extra(ag, else_node, subexpr_scope, lval, &peer_parent->peers.at(1)->base); + else_expr_result = astgen_node_extra(ag, else_node, subexpr_scope, lval, &peer_parent->peers.at(1)->base); if (else_expr_result == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; } else { @@ -5418,19 +5420,19 @@ static IrInstSrc *ir_gen_if_bool_expr(Stage1AstGen *ag, Scope *scope, AstNode *n return ir_expr_wrap(ag, scope, phi, result_loc); } -static IrInstSrc *ir_gen_prefix_op_id_lval(Stage1AstGen *ag, Scope *scope, AstNode *node, IrUnOp op_id, LVal lval) { +static IrInstSrc *astgen_prefix_op_id_lval(Stage1AstGen *ag, Scope *scope, AstNode *node, IrUnOp op_id, LVal lval) { assert(node->type == NodeTypePrefixOpExpr); AstNode *expr_node = node->data.prefix_op_expr.primary_expr; - IrInstSrc *value = ir_gen_node_extra(ag, expr_node, scope, lval, nullptr); + IrInstSrc *value = astgen_node_extra(ag, expr_node, scope, lval, nullptr); if (value == ag->codegen->invalid_inst_src) return value; return ir_build_un_op(ag, scope, node, op_id, value); } -static IrInstSrc *ir_gen_prefix_op_id(Stage1AstGen *ag, Scope *scope, AstNode *node, IrUnOp op_id) { - return ir_gen_prefix_op_id_lval(ag, scope, node, op_id, LValNone); +static IrInstSrc *astgen_prefix_op_id(Stage1AstGen *ag, Scope *scope, AstNode *node, IrUnOp op_id) { + return astgen_prefix_op_id_lval(ag, scope, node, op_id, LValNone); } static IrInstSrc *ir_expr_wrap(Stage1AstGen *ag, Scope *scope, IrInstSrc *inst, ResultLoc *result_loc) { @@ -5499,7 +5501,7 @@ static Error token_number_literal_u32(Stage1AstGen *ag, AstNode *source_node, } -static IrInstSrc *ir_gen_pointer_type(Stage1AstGen *ag, Scope *scope, AstNode *node) { +static IrInstSrc *astgen_pointer_type(Stage1AstGen *ag, Scope *scope, AstNode *node) { Error err; assert(node->type == NodeTypePointerType); @@ -5516,7 +5518,7 @@ static IrInstSrc *ir_gen_pointer_type(Stage1AstGen *ag, Scope *scope, AstNode *n IrInstSrc *sentinel; if (sentinel_expr != nullptr) { - sentinel = ir_gen_node(ag, sentinel_expr, scope); + sentinel = astgen_node(ag, sentinel_expr, scope); if (sentinel == ag->codegen->invalid_inst_src) return sentinel; } else { @@ -5525,14 +5527,14 @@ static IrInstSrc *ir_gen_pointer_type(Stage1AstGen *ag, Scope *scope, AstNode *n IrInstSrc *align_value; if (align_expr != nullptr) { - align_value = ir_gen_node(ag, align_expr, scope); + align_value = astgen_node(ag, align_expr, scope); if (align_value == ag->codegen->invalid_inst_src) return align_value; } else { align_value = nullptr; } - IrInstSrc *child_type = ir_gen_node(ag, expr_node, scope); + IrInstSrc *child_type = astgen_node(ag, expr_node, scope); if (child_type == ag->codegen->invalid_inst_src) return child_type; @@ -5564,10 +5566,10 @@ static IrInstSrc *ir_gen_pointer_type(Stage1AstGen *ag, Scope *scope, AstNode *n ptr_len, sentinel, align_value, bit_offset_start, host_int_bytes, is_allow_zero); } -static IrInstSrc *ir_gen_catch_unreachable(Stage1AstGen *ag, Scope *scope, AstNode *source_node, +static IrInstSrc *astgen_catch_unreachable(Stage1AstGen *ag, Scope *scope, AstNode *source_node, AstNode *expr_node, LVal lval, ResultLoc *result_loc) { - IrInstSrc *err_union_ptr = ir_gen_node_extra(ag, expr_node, scope, LValPtr, nullptr); + IrInstSrc *err_union_ptr = astgen_node_extra(ag, expr_node, scope, LValPtr, nullptr); if (err_union_ptr == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; @@ -5582,18 +5584,18 @@ static IrInstSrc *ir_gen_catch_unreachable(Stage1AstGen *ag, Scope *scope, AstNo return ir_expr_wrap(ag, scope, load_ptr, result_loc); } -static IrInstSrc *ir_gen_bool_not(Stage1AstGen *ag, Scope *scope, AstNode *node) { +static IrInstSrc *astgen_bool_not(Stage1AstGen *ag, Scope *scope, AstNode *node) { assert(node->type == NodeTypePrefixOpExpr); AstNode *expr_node = node->data.prefix_op_expr.primary_expr; - IrInstSrc *value = ir_gen_node(ag, expr_node, scope); + IrInstSrc *value = astgen_node(ag, expr_node, scope); if (value == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; return ir_build_bool_not(ag, scope, node, value); } -static IrInstSrc *ir_gen_prefix_op_expr(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, +static IrInstSrc *astgen_prefix_op_expr(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypePrefixOpExpr); @@ -5604,24 +5606,24 @@ static IrInstSrc *ir_gen_prefix_op_expr(Stage1AstGen *ag, Scope *scope, AstNode case PrefixOpInvalid: zig_unreachable(); case PrefixOpBoolNot: - return ir_lval_wrap(ag, scope, ir_gen_bool_not(ag, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_bool_not(ag, scope, node), lval, result_loc); case PrefixOpBinNot: - return ir_lval_wrap(ag, scope, ir_gen_prefix_op_id(ag, scope, node, IrUnOpBinNot), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_prefix_op_id(ag, scope, node, IrUnOpBinNot), lval, result_loc); case PrefixOpNegation: - return ir_lval_wrap(ag, scope, ir_gen_prefix_op_id(ag, scope, node, IrUnOpNegation), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_prefix_op_id(ag, scope, node, IrUnOpNegation), lval, result_loc); case PrefixOpNegationWrap: - return ir_lval_wrap(ag, scope, ir_gen_prefix_op_id(ag, scope, node, IrUnOpNegationWrap), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_prefix_op_id(ag, scope, node, IrUnOpNegationWrap), lval, result_loc); case PrefixOpOptional: - return ir_lval_wrap(ag, scope, ir_gen_prefix_op_id(ag, scope, node, IrUnOpOptional), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_prefix_op_id(ag, scope, node, IrUnOpOptional), lval, result_loc); case PrefixOpAddrOf: { AstNode *expr_node = node->data.prefix_op_expr.primary_expr; - return ir_lval_wrap(ag, scope, ir_gen_node_extra(ag, expr_node, scope, LValPtr, nullptr), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_node_extra(ag, expr_node, scope, LValPtr, nullptr), lval, result_loc); } } zig_unreachable(); } -static IrInstSrc *ir_gen_union_init_expr(Stage1AstGen *ag, Scope *scope, AstNode *source_node, +static IrInstSrc *astgen_union_init_expr(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *union_type, IrInstSrc *field_name, AstNode *expr_node, LVal lval, ResultLoc *parent_result_loc) { @@ -5635,7 +5637,7 @@ static IrInstSrc *ir_gen_union_init_expr(Stage1AstGen *ag, Scope *scope, AstNode ir_ref_instruction(field_ptr, ag->current_basic_block); ir_build_reset_result(ag, scope, expr_node, &result_loc_inst->base); - IrInstSrc *expr_value = ir_gen_node_extra(ag, expr_node, scope, LValNone, + IrInstSrc *expr_value = astgen_node_extra(ag, expr_node, scope, LValNone, &result_loc_inst->base); if (expr_value == ag->codegen->invalid_inst_src) return expr_value; @@ -5646,7 +5648,7 @@ static IrInstSrc *ir_gen_union_init_expr(Stage1AstGen *ag, Scope *scope, AstNode return ir_lval_wrap(ag, scope, init_union, lval, parent_result_loc); } -static IrInstSrc *ir_gen_container_init_expr(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, +static IrInstSrc *astgen_container_init_expr(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, ResultLoc *parent_result_loc) { assert(node->type == NodeTypeContainerInitExpr); @@ -5667,14 +5669,14 @@ static IrInstSrc *ir_gen_container_init_expr(Stage1AstGen *ag, Scope *scope, Ast } IrInstSrc *sentinel; if (container_init_expr->type->data.inferred_array_type.sentinel != nullptr) { - sentinel = ir_gen_node(ag, container_init_expr->type->data.inferred_array_type.sentinel, scope); + sentinel = astgen_node(ag, container_init_expr->type->data.inferred_array_type.sentinel, scope); if (sentinel == ag->codegen->invalid_inst_src) return sentinel; } else { sentinel = nullptr; } - IrInstSrc *elem_type = ir_gen_node(ag, + IrInstSrc *elem_type = astgen_node(ag, container_init_expr->type->data.inferred_array_type.child_type, scope); if (elem_type == ag->codegen->invalid_inst_src) return elem_type; @@ -5682,7 +5684,7 @@ static IrInstSrc *ir_gen_container_init_expr(Stage1AstGen *ag, Scope *scope, Ast IrInstSrc *item_count_inst = ir_build_const_usize(ag, scope, node, item_count); container_type = ir_build_array_type(ag, scope, node, item_count_inst, sentinel, elem_type); } else { - container_type = ir_gen_node(ag, container_init_expr->type, scope); + container_type = astgen_node(ag, container_init_expr->type, scope); if (container_type == ag->codegen->invalid_inst_src) return container_type; } @@ -5721,7 +5723,7 @@ static IrInstSrc *ir_gen_container_init_expr(Stage1AstGen *ag, Scope *scope, Ast ir_ref_instruction(field_ptr, ag->current_basic_block); ir_build_reset_result(ag, scope, expr_node, &result_loc_inst->base); - IrInstSrc *expr_value = ir_gen_node_extra(ag, expr_node, scope, LValNone, + IrInstSrc *expr_value = astgen_node_extra(ag, expr_node, scope, LValNone, &result_loc_inst->base); if (expr_value == ag->codegen->invalid_inst_src) return expr_value; @@ -5758,7 +5760,7 @@ static IrInstSrc *ir_gen_container_init_expr(Stage1AstGen *ag, Scope *scope, Ast ir_ref_instruction(elem_ptr, ag->current_basic_block); ir_build_reset_result(ag, scope, expr_node, &result_loc_inst->base); - IrInstSrc *expr_value = ir_gen_node_extra(ag, expr_node, scope, LValNone, + IrInstSrc *expr_value = astgen_node_extra(ag, expr_node, scope, LValNone, &result_loc_inst->base); if (expr_value == ag->codegen->invalid_inst_src) return expr_value; @@ -5812,7 +5814,7 @@ static void build_decl_var_and_init(Stage1AstGen *ag, Scope *scope, AstNode *sou ir_build_var_decl_src(ag, scope, source_node, var, nullptr, alloca); } -static IrInstSrc *ir_gen_var_decl(Stage1AstGen *ag, Scope *scope, AstNode *node) { +static IrInstSrc *astgen_var_decl(Stage1AstGen *ag, Scope *scope, AstNode *node) { assert(node->type == NodeTypeVariableDeclaration); AstNodeVariableDeclaration *variable_declaration = &node->data.variable_declaration; @@ -5827,7 +5829,7 @@ static IrInstSrc *ir_gen_var_decl(Stage1AstGen *ag, Scope *scope, AstNode *node) IrInstSrc *type_instruction; if (variable_declaration->type != nullptr) { - type_instruction = ir_gen_node(ag, variable_declaration->type, comptime_scope); + type_instruction = astgen_node(ag, variable_declaration->type, comptime_scope); if (type_instruction == ag->codegen->invalid_inst_src) return type_instruction; } else { @@ -5853,7 +5855,7 @@ static IrInstSrc *ir_gen_var_decl(Stage1AstGen *ag, Scope *scope, AstNode *node) IrInstSrc *align_value = nullptr; if (variable_declaration->align_expr != nullptr) { - align_value = ir_gen_node(ag, variable_declaration->align_expr, comptime_scope); + align_value = astgen_node(ag, variable_declaration->align_expr, comptime_scope); if (align_value == ag->codegen->invalid_inst_src) return align_value; } @@ -5888,7 +5890,7 @@ static IrInstSrc *ir_gen_var_decl(Stage1AstGen *ag, Scope *scope, AstNode *node) // so that the struct or enum from the init expression inherits the name. Buf *old_exec_name = ag->exec->name; ag->exec->name = variable_declaration->symbol; - IrInstSrc *init_value = ir_gen_node_extra(ag, variable_declaration->expr, init_scope, + IrInstSrc *init_value = astgen_node_extra(ag, variable_declaration->expr, init_scope, LValNone, init_result_loc); ag->exec->name = old_exec_name; @@ -5904,7 +5906,7 @@ static IrInstSrc *ir_gen_var_decl(Stage1AstGen *ag, Scope *scope, AstNode *node) return ir_build_var_decl_src(ag, scope, node, var, align_value, alloca); } -static IrInstSrc *ir_gen_while_expr(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, +static IrInstSrc *astgen_while_expr(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypeWhileExpr); @@ -5942,7 +5944,7 @@ static IrInstSrc *ir_gen_while_expr(Stage1AstGen *ag, Scope *scope, AstNode *nod payload_scope = subexpr_scope; } ScopeExpr *spill_scope = create_expr_scope(ag->codegen, node, payload_scope); - IrInstSrc *err_val_ptr = ir_gen_node_extra(ag, node->data.while_expr.condition, subexpr_scope, + IrInstSrc *err_val_ptr = astgen_node_extra(ag, node->data.while_expr.condition, subexpr_scope, LValPtr, nullptr); if (err_val_ptr == ag->codegen->invalid_inst_src) return err_val_ptr; @@ -5990,8 +5992,8 @@ static IrInstSrc *ir_gen_while_expr(Stage1AstGen *ag, Scope *scope, AstNode *nod // Note the body block of the loop is not the place that lval and result_loc are used - // it's actually in break statements, handled similarly to return statements. - // That is why we set those values in loop_scope above and not in this ir_gen_node call. - IrInstSrc *body_result = ir_gen_node(ag, node->data.while_expr.body, &loop_scope->base); + // That is why we set those values in loop_scope above and not in this astgen_node call. + IrInstSrc *body_result = astgen_node(ag, node->data.while_expr.body, &loop_scope->base); if (body_result == ag->codegen->invalid_inst_src) return body_result; @@ -6006,7 +6008,7 @@ static IrInstSrc *ir_gen_while_expr(Stage1AstGen *ag, Scope *scope, AstNode *nod if (continue_expr_node) { ir_set_cursor_at_end_and_append_block(ag, continue_block); - IrInstSrc *expr_result = ir_gen_node(ag, continue_expr_node, payload_scope); + IrInstSrc *expr_result = astgen_node(ag, continue_expr_node, payload_scope); if (expr_result == ag->codegen->invalid_inst_src) return expr_result; if (!instr_is_unreachable(expr_result)) { @@ -6032,7 +6034,7 @@ static IrInstSrc *ir_gen_while_expr(Stage1AstGen *ag, Scope *scope, AstNode *nod } ResultLocPeer *peer_result = create_peer_result(peer_parent); peer_parent->peers.append(peer_result); - IrInstSrc *else_result = ir_gen_node_extra(ag, else_node, err_scope, lval, &peer_result->base); + IrInstSrc *else_result = astgen_node_extra(ag, else_node, err_scope, lval, &peer_result->base); if (else_result == ag->codegen->invalid_inst_src) return else_result; if (!instr_is_unreachable(else_result)) @@ -6063,7 +6065,7 @@ static IrInstSrc *ir_gen_while_expr(Stage1AstGen *ag, Scope *scope, AstNode *nod true, false, false, is_comptime); Scope *child_scope = payload_var->child_scope; ScopeExpr *spill_scope = create_expr_scope(ag->codegen, node, child_scope); - IrInstSrc *maybe_val_ptr = ir_gen_node_extra(ag, node->data.while_expr.condition, subexpr_scope, + IrInstSrc *maybe_val_ptr = astgen_node_extra(ag, node->data.while_expr.condition, subexpr_scope, LValPtr, nullptr); if (maybe_val_ptr == ag->codegen->invalid_inst_src) return maybe_val_ptr; @@ -6108,8 +6110,8 @@ static IrInstSrc *ir_gen_while_expr(Stage1AstGen *ag, Scope *scope, AstNode *nod // Note the body block of the loop is not the place that lval and result_loc are used - // it's actually in break statements, handled similarly to return statements. - // That is why we set those values in loop_scope above and not in this ir_gen_node call. - IrInstSrc *body_result = ir_gen_node(ag, node->data.while_expr.body, &loop_scope->base); + // That is why we set those values in loop_scope above and not in this astgen_node call. + IrInstSrc *body_result = astgen_node(ag, node->data.while_expr.body, &loop_scope->base); if (body_result == ag->codegen->invalid_inst_src) return body_result; @@ -6124,7 +6126,7 @@ static IrInstSrc *ir_gen_while_expr(Stage1AstGen *ag, Scope *scope, AstNode *nod if (continue_expr_node) { ir_set_cursor_at_end_and_append_block(ag, continue_block); - IrInstSrc *expr_result = ir_gen_node(ag, continue_expr_node, child_scope); + IrInstSrc *expr_result = astgen_node(ag, continue_expr_node, child_scope); if (expr_result == ag->codegen->invalid_inst_src) return expr_result; if (!instr_is_unreachable(expr_result)) { @@ -6142,7 +6144,7 @@ static IrInstSrc *ir_gen_while_expr(Stage1AstGen *ag, Scope *scope, AstNode *nod } ResultLocPeer *peer_result = create_peer_result(peer_parent); peer_parent->peers.append(peer_result); - else_result = ir_gen_node_extra(ag, else_node, scope, lval, &peer_result->base); + else_result = astgen_node_extra(ag, else_node, scope, lval, &peer_result->base); if (else_result == ag->codegen->invalid_inst_src) return else_result; if (!instr_is_unreachable(else_result)) @@ -6166,7 +6168,7 @@ static IrInstSrc *ir_gen_while_expr(Stage1AstGen *ag, Scope *scope, AstNode *nod return ir_expr_wrap(ag, scope, phi, result_loc); } else { ir_set_cursor_at_end_and_append_block(ag, cond_block); - IrInstSrc *cond_val = ir_gen_node(ag, node->data.while_expr.condition, scope); + IrInstSrc *cond_val = astgen_node(ag, node->data.while_expr.condition, scope); if (cond_val == ag->codegen->invalid_inst_src) return cond_val; Stage1ZirBasicBlock *after_cond_block = ag->current_basic_block; @@ -6204,8 +6206,8 @@ static IrInstSrc *ir_gen_while_expr(Stage1AstGen *ag, Scope *scope, AstNode *nod // Note the body block of the loop is not the place that lval and result_loc are used - // it's actually in break statements, handled similarly to return statements. - // That is why we set those values in loop_scope above and not in this ir_gen_node call. - IrInstSrc *body_result = ir_gen_node(ag, node->data.while_expr.body, &loop_scope->base); + // That is why we set those values in loop_scope above and not in this astgen_node call. + IrInstSrc *body_result = astgen_node(ag, node->data.while_expr.body, &loop_scope->base); if (body_result == ag->codegen->invalid_inst_src) return body_result; @@ -6220,7 +6222,7 @@ static IrInstSrc *ir_gen_while_expr(Stage1AstGen *ag, Scope *scope, AstNode *nod if (continue_expr_node) { ir_set_cursor_at_end_and_append_block(ag, continue_block); - IrInstSrc *expr_result = ir_gen_node(ag, continue_expr_node, subexpr_scope); + IrInstSrc *expr_result = astgen_node(ag, continue_expr_node, subexpr_scope); if (expr_result == ag->codegen->invalid_inst_src) return expr_result; if (!instr_is_unreachable(expr_result)) { @@ -6239,7 +6241,7 @@ static IrInstSrc *ir_gen_while_expr(Stage1AstGen *ag, Scope *scope, AstNode *nod ResultLocPeer *peer_result = create_peer_result(peer_parent); peer_parent->peers.append(peer_result); - else_result = ir_gen_node_extra(ag, else_node, subexpr_scope, lval, &peer_result->base); + else_result = astgen_node_extra(ag, else_node, subexpr_scope, lval, &peer_result->base); if (else_result == ag->codegen->invalid_inst_src) return else_result; if (!instr_is_unreachable(else_result)) @@ -6264,7 +6266,7 @@ static IrInstSrc *ir_gen_while_expr(Stage1AstGen *ag, Scope *scope, AstNode *nod } } -static IrInstSrc *ir_gen_for_expr(Stage1AstGen *ag, Scope *parent_scope, AstNode *node, LVal lval, +static IrInstSrc *astgen_for_expr(Stage1AstGen *ag, Scope *parent_scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypeForExpr); @@ -6283,7 +6285,7 @@ static IrInstSrc *ir_gen_for_expr(Stage1AstGen *ag, Scope *parent_scope, AstNode ScopeExpr *spill_scope = create_expr_scope(ag->codegen, node, parent_scope); - IrInstSrc *array_val_ptr = ir_gen_node_extra(ag, array_node, &spill_scope->base, LValPtr, nullptr); + IrInstSrc *array_val_ptr = astgen_node_extra(ag, array_node, &spill_scope->base, LValPtr, nullptr); if (array_val_ptr == ag->codegen->invalid_inst_src) return array_val_ptr; @@ -6362,8 +6364,8 @@ static IrInstSrc *ir_gen_for_expr(Stage1AstGen *ag, Scope *parent_scope, AstNode // Note the body block of the loop is not the place that lval and result_loc are used - // it's actually in break statements, handled similarly to return statements. - // That is why we set those values in loop_scope above and not in this ir_gen_node call. - IrInstSrc *body_result = ir_gen_node(ag, body_node, &loop_scope->base); + // That is why we set those values in loop_scope above and not in this astgen_node call. + IrInstSrc *body_result = astgen_node(ag, body_node, &loop_scope->base); if (body_result == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; @@ -6390,7 +6392,7 @@ static IrInstSrc *ir_gen_for_expr(Stage1AstGen *ag, Scope *parent_scope, AstNode } ResultLocPeer *peer_result = create_peer_result(peer_parent); peer_parent->peers.append(peer_result); - else_result = ir_gen_node_extra(ag, else_node, parent_scope, LValNone, &peer_result->base); + else_result = astgen_node_extra(ag, else_node, parent_scope, LValNone, &peer_result->base); if (else_result == ag->codegen->invalid_inst_src) return else_result; if (!instr_is_unreachable(else_result)) @@ -6415,19 +6417,25 @@ static IrInstSrc *ir_gen_for_expr(Stage1AstGen *ag, Scope *parent_scope, AstNode return ir_lval_wrap(ag, parent_scope, phi, lval, result_loc); } -static IrInstSrc *ir_gen_bool_literal(Stage1AstGen *ag, Scope *scope, AstNode *node) { +static IrInstSrc *astgen_bool_literal(Stage1AstGen *ag, Scope *scope, AstNode *node) { assert(node->type == NodeTypeBoolLiteral); return ir_build_const_bool(ag, scope, node, node->data.bool_literal.value); } -static IrInstSrc *ir_gen_enum_literal(Stage1AstGen *ag, Scope *scope, AstNode *node) { +static IrInstSrc *astgen_enum_literal(Stage1AstGen *ag, Scope *scope, AstNode *node) { assert(node->type == NodeTypeEnumLiteral); - RootStruct *root_struct = node->owner->data.structure.root_struct; - Buf *name = token_identifier_buf(root_struct, node->main_token + 1); - return ir_build_const_enum_literal(ag, scope, node, name); + // Currently, stage1 runs astgen for every comptime function call, + // resulting the allocation here wasting memory. As a workaround until + // the code is adjusted to make astgen run only once per source node, + // we memoize the result into the AST here. + if (node->data.enum_literal.name == nullptr) { + RootStruct *root_struct = node->owner->data.structure.root_struct; + node->data.enum_literal.name = token_identifier_buf(root_struct, node->main_token + 1); + } + return ir_build_const_enum_literal(ag, scope, node, node->data.enum_literal.name); } -static IrInstSrc *ir_gen_string_literal(Stage1AstGen *ag, Scope *scope, AstNode *node) { +static IrInstSrc *astgen_string_literal(Stage1AstGen *ag, Scope *scope, AstNode *node) { Error err; assert(node->type == NodeTypeStringLiteral); @@ -6465,10 +6473,11 @@ static IrInstSrc *ir_gen_string_literal(Stage1AstGen *ag, Scope *scope, AstNode } else { zig_unreachable(); } + return ir_build_const_str_lit(ag, scope, node, str); } -static IrInstSrc *ir_gen_array_type(Stage1AstGen *ag, Scope *scope, AstNode *node) { +static IrInstSrc *astgen_array_type(Stage1AstGen *ag, Scope *scope, AstNode *node) { assert(node->type == NodeTypeArrayType); AstNode *size_node = node->data.array_type.size; @@ -6483,7 +6492,7 @@ static IrInstSrc *ir_gen_array_type(Stage1AstGen *ag, Scope *scope, AstNode *nod IrInstSrc *sentinel; if (sentinel_expr != nullptr) { - sentinel = ir_gen_node(ag, sentinel_expr, comptime_scope); + sentinel = astgen_node(ag, sentinel_expr, comptime_scope); if (sentinel == ag->codegen->invalid_inst_src) return sentinel; } else { @@ -6508,11 +6517,11 @@ static IrInstSrc *ir_gen_array_type(Stage1AstGen *ag, Scope *scope, AstNode *nod return ag->codegen->invalid_inst_src; } - IrInstSrc *size_value = ir_gen_node(ag, size_node, comptime_scope); + IrInstSrc *size_value = astgen_node(ag, size_node, comptime_scope); if (size_value == ag->codegen->invalid_inst_src) return size_value; - IrInstSrc *child_type = ir_gen_node(ag, child_type_node, comptime_scope); + IrInstSrc *child_type = astgen_node(ag, child_type_node, comptime_scope); if (child_type == ag->codegen->invalid_inst_src) return child_type; @@ -6520,14 +6529,14 @@ static IrInstSrc *ir_gen_array_type(Stage1AstGen *ag, Scope *scope, AstNode *nod } else { IrInstSrc *align_value; if (align_expr != nullptr) { - align_value = ir_gen_node(ag, align_expr, comptime_scope); + align_value = astgen_node(ag, align_expr, comptime_scope); if (align_value == ag->codegen->invalid_inst_src) return align_value; } else { align_value = nullptr; } - IrInstSrc *child_type = ir_gen_node(ag, child_type_node, comptime_scope); + IrInstSrc *child_type = astgen_node(ag, child_type_node, comptime_scope); if (child_type == ag->codegen->invalid_inst_src) return child_type; @@ -6536,14 +6545,14 @@ static IrInstSrc *ir_gen_array_type(Stage1AstGen *ag, Scope *scope, AstNode *nod } } -static IrInstSrc *ir_gen_anyframe_type(Stage1AstGen *ag, Scope *scope, AstNode *node) { +static IrInstSrc *astgen_anyframe_type(Stage1AstGen *ag, Scope *scope, AstNode *node) { assert(node->type == NodeTypeAnyFrameType); AstNode *payload_type_node = node->data.anyframe_type.payload_type; IrInstSrc *payload_type_value = nullptr; if (payload_type_node != nullptr) { - payload_type_value = ir_gen_node(ag, payload_type_node, scope); + payload_type_value = astgen_node(ag, payload_type_node, scope); if (payload_type_value == ag->codegen->invalid_inst_src) return payload_type_value; @@ -6552,16 +6561,16 @@ static IrInstSrc *ir_gen_anyframe_type(Stage1AstGen *ag, Scope *scope, AstNode * return ir_build_anyframe_type(ag, scope, node, payload_type_value); } -static IrInstSrc *ir_gen_undefined_literal(Stage1AstGen *ag, Scope *scope, AstNode *node) { +static IrInstSrc *astgen_undefined_literal(Stage1AstGen *ag, Scope *scope, AstNode *node) { assert(node->type == NodeTypeUndefinedLiteral); return ir_build_const_undefined(ag, scope, node); } -static IrInstSrc *ir_gen_asm_expr(Stage1AstGen *ag, Scope *scope, AstNode *node) { +static IrInstSrc *astgen_asm_expr(Stage1AstGen *ag, Scope *scope, AstNode *node) { assert(node->type == NodeTypeAsmExpr); AstNodeAsmExpr *asm_expr = &node->data.asm_expr; - IrInstSrc *asm_template = ir_gen_node(ag, asm_expr->asm_template, scope); + IrInstSrc *asm_template = astgen_node(ag, asm_expr->asm_template, scope); if (asm_template == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; @@ -6601,7 +6610,7 @@ static IrInstSrc *ir_gen_asm_expr(Stage1AstGen *ag, Scope *scope, AstNode *node) if (asm_output->return_type) { return_count += 1; - IrInstSrc *return_type = ir_gen_node(ag, asm_output->return_type, scope); + IrInstSrc *return_type = astgen_node(ag, asm_output->return_type, scope); if (return_type == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; if (return_count > 1) { @@ -6612,7 +6621,7 @@ static IrInstSrc *ir_gen_asm_expr(Stage1AstGen *ag, Scope *scope, AstNode *node) output_types[i] = return_type; } else { Buf *variable_name = asm_output->variable_name; - // TODO there is some duplication here with ir_gen_symbol. I need to do a full audit of how + // TODO there is some duplication here with astgen_identifier. I need to do a full audit of how // inline assembly works. https://github.com/ziglang/zig/issues/215 ZigVar *var = find_variable(ag->codegen, scope, variable_name, nullptr); if (var) { @@ -6635,7 +6644,7 @@ static IrInstSrc *ir_gen_asm_expr(Stage1AstGen *ag, Scope *scope, AstNode *node) } for (size_t i = 0; i < asm_expr->input_list.length; i += 1) { AsmInput *asm_input = asm_expr->input_list.at(i); - IrInstSrc *input_value = ir_gen_node(ag, asm_input->expr, scope); + IrInstSrc *input_value = astgen_node(ag, asm_input->expr, scope); if (input_value == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; @@ -6646,7 +6655,7 @@ static IrInstSrc *ir_gen_asm_expr(Stage1AstGen *ag, Scope *scope, AstNode *node) output_vars, return_count, is_volatile, false); } -static IrInstSrc *ir_gen_if_optional_expr(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, +static IrInstSrc *astgen_if_optional_expr(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypeIfOptional); @@ -6660,7 +6669,7 @@ static IrInstSrc *ir_gen_if_optional_expr(Stage1AstGen *ag, Scope *scope, AstNod ScopeExpr *spill_scope = create_expr_scope(ag->codegen, expr_node, scope); spill_scope->spill_harder = true; - IrInstSrc *maybe_val_ptr = ir_gen_node_extra(ag, expr_node, &spill_scope->base, LValPtr, nullptr); + IrInstSrc *maybe_val_ptr = astgen_node_extra(ag, expr_node, &spill_scope->base, LValPtr, nullptr); if (maybe_val_ptr == ag->codegen->invalid_inst_src) return maybe_val_ptr; @@ -6701,7 +6710,7 @@ static IrInstSrc *ir_gen_if_optional_expr(Stage1AstGen *ag, Scope *scope, AstNod } else { var_scope = subexpr_scope; } - IrInstSrc *then_expr_result = ir_gen_node_extra(ag, then_node, var_scope, lval, + IrInstSrc *then_expr_result = astgen_node_extra(ag, then_node, var_scope, lval, &peer_parent->peers.at(0)->base); if (then_expr_result == ag->codegen->invalid_inst_src) return then_expr_result; @@ -6712,7 +6721,7 @@ static IrInstSrc *ir_gen_if_optional_expr(Stage1AstGen *ag, Scope *scope, AstNod ir_set_cursor_at_end_and_append_block(ag, else_block); IrInstSrc *else_expr_result; if (else_node) { - else_expr_result = ir_gen_node_extra(ag, else_node, subexpr_scope, lval, &peer_parent->peers.at(1)->base); + else_expr_result = astgen_node_extra(ag, else_node, subexpr_scope, lval, &peer_parent->peers.at(1)->base); if (else_expr_result == ag->codegen->invalid_inst_src) return else_expr_result; } else { @@ -6735,7 +6744,7 @@ static IrInstSrc *ir_gen_if_optional_expr(Stage1AstGen *ag, Scope *scope, AstNod return ir_expr_wrap(ag, scope, phi, result_loc); } -static IrInstSrc *ir_gen_if_err_expr(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, +static IrInstSrc *astgen_if_err_expr(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypeIfErrorExpr); @@ -6748,7 +6757,7 @@ static IrInstSrc *ir_gen_if_err_expr(Stage1AstGen *ag, Scope *scope, AstNode *no Buf *var_symbol = node->data.if_err_expr.var_symbol; Buf *err_symbol = node->data.if_err_expr.err_symbol; - IrInstSrc *err_val_ptr = ir_gen_node_extra(ag, target_node, scope, LValPtr, nullptr); + IrInstSrc *err_val_ptr = astgen_node_extra(ag, target_node, scope, LValPtr, nullptr); if (err_val_ptr == ag->codegen->invalid_inst_src) return err_val_ptr; @@ -6784,7 +6793,7 @@ static IrInstSrc *ir_gen_if_err_expr(Stage1AstGen *ag, Scope *scope, AstNode *no } else { var_scope = subexpr_scope; } - IrInstSrc *then_expr_result = ir_gen_node_extra(ag, then_node, var_scope, lval, + IrInstSrc *then_expr_result = astgen_node_extra(ag, then_node, var_scope, lval, &peer_parent->peers.at(0)->base); if (then_expr_result == ag->codegen->invalid_inst_src) return then_expr_result; @@ -6810,7 +6819,7 @@ static IrInstSrc *ir_gen_if_err_expr(Stage1AstGen *ag, Scope *scope, AstNode *no } else { err_var_scope = subexpr_scope; } - else_expr_result = ir_gen_node_extra(ag, else_node, err_var_scope, lval, &peer_parent->peers.at(1)->base); + else_expr_result = astgen_node_extra(ag, else_node, err_var_scope, lval, &peer_parent->peers.at(1)->base); if (else_expr_result == ag->codegen->invalid_inst_src) return else_expr_result; } else { @@ -6833,7 +6842,7 @@ static IrInstSrc *ir_gen_if_err_expr(Stage1AstGen *ag, Scope *scope, AstNode *no return ir_expr_wrap(ag, scope, phi, result_loc); } -static bool ir_gen_switch_prong_expr(Stage1AstGen *ag, Scope *scope, AstNode *switch_node, AstNode *prong_node, +static bool astgen_switch_prong_expr(Stage1AstGen *ag, Scope *scope, AstNode *switch_node, AstNode *prong_node, Stage1ZirBasicBlock *end_block, IrInstSrc *is_comptime, IrInstSrc *var_is_comptime, IrInstSrc *target_value_ptr, IrInstSrc **prong_values, size_t prong_values_len, ZigList *incoming_blocks, ZigList *incoming_values, @@ -6877,7 +6886,7 @@ static bool ir_gen_switch_prong_expr(Stage1AstGen *ag, Scope *scope, AstNode *sw child_scope = scope; } - IrInstSrc *expr_result = ir_gen_node_extra(ag, expr_node, child_scope, lval, result_loc); + IrInstSrc *expr_result = astgen_node_extra(ag, expr_node, child_scope, lval, result_loc); if (expr_result == ag->codegen->invalid_inst_src) return false; if (!instr_is_unreachable(expr_result)) @@ -6887,13 +6896,13 @@ static bool ir_gen_switch_prong_expr(Stage1AstGen *ag, Scope *scope, AstNode *sw return true; } -static IrInstSrc *ir_gen_switch_expr(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, +static IrInstSrc *astgen_switch_expr(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypeSwitchExpr); AstNode *target_node = node->data.switch_expr.expr; - IrInstSrc *target_value_ptr = ir_gen_node_extra(ag, target_node, scope, LValPtr, nullptr); + IrInstSrc *target_value_ptr = astgen_node_extra(ag, target_node, scope, LValPtr, nullptr); if (target_value_ptr == ag->codegen->invalid_inst_src) return target_value_ptr; IrInstSrc *target_value = ir_build_switch_target(ag, scope, node, target_value_ptr); @@ -6949,11 +6958,11 @@ static IrInstSrc *ir_gen_switch_expr(Stage1AstGen *ag, Scope *scope, AstNode *no AstNode *start_node = item_node->data.switch_range.start; AstNode *end_node = item_node->data.switch_range.end; - IrInstSrc *start_value = ir_gen_node(ag, start_node, comptime_scope); + IrInstSrc *start_value = astgen_node(ag, start_node, comptime_scope); if (start_value == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; - IrInstSrc *end_value = ir_gen_node(ag, end_node, comptime_scope); + IrInstSrc *end_value = astgen_node(ag, end_node, comptime_scope); if (end_value == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; @@ -6973,7 +6982,7 @@ static IrInstSrc *ir_gen_switch_expr(Stage1AstGen *ag, Scope *scope, AstNode *no ok_bit = both_ok; } } else { - IrInstSrc *item_value = ir_gen_node(ag, item_node, comptime_scope); + IrInstSrc *item_value = astgen_node(ag, item_node, comptime_scope); if (item_value == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; @@ -7007,7 +7016,7 @@ static IrInstSrc *ir_gen_switch_expr(Stage1AstGen *ag, Scope *scope, AstNode *no } peer_parent->peers.append(this_peer_result_loc); ir_set_cursor_at_end_and_append_block(ag, range_block_yes); - if (!ir_gen_switch_prong_expr(ag, subexpr_scope, node, prong_node, end_block, + if (!astgen_switch_prong_expr(ag, subexpr_scope, node, prong_node, end_block, is_comptime, var_is_comptime, target_value_ptr, nullptr, 0, &incoming_blocks, &incoming_values, nullptr, LValNone, &this_peer_result_loc->base)) { @@ -7058,7 +7067,7 @@ static IrInstSrc *ir_gen_switch_expr(Stage1AstGen *ag, Scope *scope, AstNode *no } peer_parent->peers.append(this_peer_result_loc); ir_set_cursor_at_end_and_append_block(ag, else_block); - if (!ir_gen_switch_prong_expr(ag, subexpr_scope, node, prong_node, end_block, + if (!astgen_switch_prong_expr(ag, subexpr_scope, node, prong_node, end_block, is_comptime, var_is_comptime, target_value_ptr, nullptr, 0, &incoming_blocks, &incoming_values, &switch_else_var, LValNone, &this_peer_result_loc->base)) { @@ -7088,7 +7097,7 @@ static IrInstSrc *ir_gen_switch_expr(Stage1AstGen *ag, Scope *scope, AstNode *no AstNode *item_node = prong_node->data.switch_prong.items.at(item_i); assert(item_node->type != NodeTypeSwitchRange); - IrInstSrc *item_value = ir_gen_node(ag, item_node, comptime_scope); + IrInstSrc *item_value = astgen_node(ag, item_node, comptime_scope); if (item_value == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; @@ -7109,7 +7118,7 @@ static IrInstSrc *ir_gen_switch_expr(Stage1AstGen *ag, Scope *scope, AstNode *no } peer_parent->peers.append(this_peer_result_loc); ir_set_cursor_at_end_and_append_block(ag, prong_block); - if (!ir_gen_switch_prong_expr(ag, subexpr_scope, node, prong_node, end_block, + if (!astgen_switch_prong_expr(ag, subexpr_scope, node, prong_node, end_block, is_comptime, var_is_comptime, target_value_ptr, items, prong_item_count, &incoming_blocks, &incoming_values, nullptr, LValNone, &this_peer_result_loc->base)) { @@ -7165,23 +7174,23 @@ static IrInstSrc *ir_gen_switch_expr(Stage1AstGen *ag, Scope *scope, AstNode *no return ir_lval_wrap(ag, scope, result_instruction, lval, result_loc); } -static IrInstSrc *ir_gen_comptime(Stage1AstGen *ag, Scope *parent_scope, AstNode *node, LVal lval) { +static IrInstSrc *astgen_comptime(Stage1AstGen *ag, Scope *parent_scope, AstNode *node, LVal lval) { assert(node->type == NodeTypeCompTime); Scope *child_scope = create_comptime_scope(ag->codegen, node, parent_scope); // purposefully pass null for result_loc and let EndExpr handle it - return ir_gen_node_extra(ag, node->data.comptime_expr.expr, child_scope, lval, nullptr); + return astgen_node_extra(ag, node->data.comptime_expr.expr, child_scope, lval, nullptr); } -static IrInstSrc *ir_gen_nosuspend(Stage1AstGen *ag, Scope *parent_scope, AstNode *node, LVal lval) { +static IrInstSrc *astgen_nosuspend(Stage1AstGen *ag, Scope *parent_scope, AstNode *node, LVal lval) { assert(node->type == NodeTypeNoSuspend); Scope *child_scope = create_nosuspend_scope(ag->codegen, node, parent_scope); // purposefully pass null for result_loc and let EndExpr handle it - return ir_gen_node_extra(ag, node->data.nosuspend_expr.expr, child_scope, lval, nullptr); + return astgen_node_extra(ag, node->data.nosuspend_expr.expr, child_scope, lval, nullptr); } -static IrInstSrc *ir_gen_return_from_block(Stage1AstGen *ag, Scope *break_scope, AstNode *node, ScopeBlock *block_scope) { +static IrInstSrc *astgen_return_from_block(Stage1AstGen *ag, Scope *break_scope, AstNode *node, ScopeBlock *block_scope) { IrInstSrc *is_comptime; if (ir_should_inline(ag->exec, break_scope)) { is_comptime = ir_build_const_bool(ag, break_scope, node, true); @@ -7194,7 +7203,7 @@ static IrInstSrc *ir_gen_return_from_block(Stage1AstGen *ag, Scope *break_scope, ResultLocPeer *peer_result = create_peer_result(block_scope->peer_parent); block_scope->peer_parent->peers.append(peer_result); - result_value = ir_gen_node_extra(ag, node->data.break_expr.expr, break_scope, block_scope->lval, + result_value = astgen_node_extra(ag, node->data.break_expr.expr, break_scope, block_scope->lval, &peer_result->base); if (result_value == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; @@ -7203,7 +7212,7 @@ static IrInstSrc *ir_gen_return_from_block(Stage1AstGen *ag, Scope *break_scope, } Stage1ZirBasicBlock *dest_block = block_scope->end_block; - if (!ir_gen_defers_for_block(ag, break_scope, dest_block->scope, nullptr, nullptr)) + if (!astgen_defers_for_block(ag, break_scope, dest_block->scope, nullptr, nullptr)) return ag->codegen->invalid_inst_src; block_scope->incoming_blocks->append(ag->current_basic_block); @@ -7211,7 +7220,7 @@ static IrInstSrc *ir_gen_return_from_block(Stage1AstGen *ag, Scope *break_scope, return ir_build_br(ag, break_scope, node, dest_block, is_comptime); } -static IrInstSrc *ir_gen_break(Stage1AstGen *ag, Scope *break_scope, AstNode *node) { +static IrInstSrc *astgen_break(Stage1AstGen *ag, Scope *break_scope, AstNode *node) { assert(node->type == NodeTypeBreak); // Search up the scope. We'll find one of these things first: @@ -7250,7 +7259,7 @@ static IrInstSrc *ir_gen_break(Stage1AstGen *ag, Scope *break_scope, AstNode *no { assert(this_block_scope->end_block != nullptr); this_block_scope->name_used = true; - return ir_gen_return_from_block(ag, break_scope, node, this_block_scope); + return astgen_return_from_block(ag, break_scope, node, this_block_scope); } } else if (search_scope->id == ScopeIdSuspend) { add_node_error(ag->codegen, node, buf_sprintf("cannot break out of suspend block")); @@ -7271,7 +7280,7 @@ static IrInstSrc *ir_gen_break(Stage1AstGen *ag, Scope *break_scope, AstNode *no ResultLocPeer *peer_result = create_peer_result(loop_scope->peer_parent); loop_scope->peer_parent->peers.append(peer_result); - result_value = ir_gen_node_extra(ag, node->data.break_expr.expr, break_scope, + result_value = astgen_node_extra(ag, node->data.break_expr.expr, break_scope, loop_scope->lval, &peer_result->base); if (result_value == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; @@ -7280,7 +7289,7 @@ static IrInstSrc *ir_gen_break(Stage1AstGen *ag, Scope *break_scope, AstNode *no } Stage1ZirBasicBlock *dest_block = loop_scope->break_block; - if (!ir_gen_defers_for_block(ag, break_scope, dest_block->scope, nullptr, nullptr)) + if (!astgen_defers_for_block(ag, break_scope, dest_block->scope, nullptr, nullptr)) return ag->codegen->invalid_inst_src; loop_scope->incoming_blocks->append(ag->current_basic_block); @@ -7288,7 +7297,7 @@ static IrInstSrc *ir_gen_break(Stage1AstGen *ag, Scope *break_scope, AstNode *no return ir_build_br(ag, break_scope, node, dest_block, is_comptime); } -static IrInstSrc *ir_gen_continue(Stage1AstGen *ag, Scope *continue_scope, AstNode *node) { +static IrInstSrc *astgen_continue(Stage1AstGen *ag, Scope *continue_scope, AstNode *node) { assert(node->type == NodeTypeContinue); // Search up the scope. We'll find one of these things first: @@ -7342,17 +7351,17 @@ static IrInstSrc *ir_gen_continue(Stage1AstGen *ag, Scope *continue_scope, AstNo runtime_scopes.deinit(); Stage1ZirBasicBlock *dest_block = loop_scope->continue_block; - if (!ir_gen_defers_for_block(ag, continue_scope, dest_block->scope, nullptr, nullptr)) + if (!astgen_defers_for_block(ag, continue_scope, dest_block->scope, nullptr, nullptr)) return ag->codegen->invalid_inst_src; return ir_mark_gen(ir_build_br(ag, continue_scope, node, dest_block, is_comptime)); } -static IrInstSrc *ir_gen_error_type(Stage1AstGen *ag, Scope *scope, AstNode *node) { +static IrInstSrc *astgen_error_type(Stage1AstGen *ag, Scope *scope, AstNode *node) { assert(node->type == NodeTypeErrorType); return ir_build_const_type(ag, scope, node, ag->codegen->builtin_types.entry_global_error_set); } -static IrInstSrc *ir_gen_defer(Stage1AstGen *ag, Scope *parent_scope, AstNode *node) { +static IrInstSrc *astgen_defer(Stage1AstGen *ag, Scope *parent_scope, AstNode *node) { assert(node->type == NodeTypeDefer); ScopeDefer *defer_child_scope = create_defer_scope(ag->codegen, node, parent_scope); @@ -7364,7 +7373,7 @@ static IrInstSrc *ir_gen_defer(Stage1AstGen *ag, Scope *parent_scope, AstNode *n return ir_build_const_void(ag, parent_scope, node); } -static IrInstSrc *ir_gen_slice(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { +static IrInstSrc *astgen_slice(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypeSliceExpr); AstNodeSliceExpr *slice_expr = &node->data.slice_expr; @@ -7373,17 +7382,17 @@ static IrInstSrc *ir_gen_slice(Stage1AstGen *ag, Scope *scope, AstNode *node, LV AstNode *end_node = slice_expr->end; AstNode *sentinel_node = slice_expr->sentinel; - IrInstSrc *ptr_value = ir_gen_node_extra(ag, array_node, scope, LValPtr, nullptr); + IrInstSrc *ptr_value = astgen_node_extra(ag, array_node, scope, LValPtr, nullptr); if (ptr_value == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; - IrInstSrc *start_value = ir_gen_node(ag, start_node, scope); + IrInstSrc *start_value = astgen_node(ag, start_node, scope); if (start_value == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; IrInstSrc *end_value; if (end_node) { - end_value = ir_gen_node(ag, end_node, scope); + end_value = astgen_node(ag, end_node, scope); if (end_value == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; } else { @@ -7392,7 +7401,7 @@ static IrInstSrc *ir_gen_slice(Stage1AstGen *ag, Scope *scope, AstNode *node, LV IrInstSrc *sentinel_value; if (sentinel_node) { - sentinel_value = ir_gen_node(ag, sentinel_node, scope); + sentinel_value = astgen_node(ag, sentinel_node, scope); if (sentinel_value == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; } else { @@ -7404,7 +7413,7 @@ static IrInstSrc *ir_gen_slice(Stage1AstGen *ag, Scope *scope, AstNode *node, LV return ir_lval_wrap(ag, scope, slice, lval, result_loc); } -static IrInstSrc *ir_gen_catch(Stage1AstGen *ag, Scope *parent_scope, AstNode *node, LVal lval, +static IrInstSrc *astgen_catch(Stage1AstGen *ag, Scope *parent_scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypeCatchExpr); @@ -7420,14 +7429,14 @@ static IrInstSrc *ir_gen_catch(Stage1AstGen *ag, Scope *parent_scope, AstNode *n add_node_error(ag->codegen, var_node, buf_sprintf("unused variable: '%s'", buf_ptr(var_name))); return ag->codegen->invalid_inst_src; } - return ir_gen_catch_unreachable(ag, parent_scope, node, op1_node, lval, result_loc); + return astgen_catch_unreachable(ag, parent_scope, node, op1_node, lval, result_loc); } ScopeExpr *spill_scope = create_expr_scope(ag->codegen, op1_node, parent_scope); spill_scope->spill_harder = true; - IrInstSrc *err_union_ptr = ir_gen_node_extra(ag, op1_node, &spill_scope->base, LValPtr, nullptr); + IrInstSrc *err_union_ptr = astgen_node_extra(ag, op1_node, &spill_scope->base, LValPtr, nullptr); if (err_union_ptr == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; @@ -7465,7 +7474,7 @@ static IrInstSrc *ir_gen_catch(Stage1AstGen *ag, Scope *parent_scope, AstNode *n } else { err_scope = subexpr_scope; } - IrInstSrc *err_result = ir_gen_node_extra(ag, op2_node, err_scope, LValNone, &peer_parent->peers.at(0)->base); + IrInstSrc *err_result = astgen_node_extra(ag, op2_node, err_scope, LValNone, &peer_parent->peers.at(0)->base); if (err_result == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; Stage1ZirBasicBlock *after_err_block = ag->current_basic_block; @@ -7535,7 +7544,7 @@ Buf *get_anon_type_name(CodeGen *codegen, Stage1Zir *exec, const char *kind_name } } -static IrInstSrc *ir_gen_container_decl(Stage1AstGen *ag, Scope *parent_scope, AstNode *node) { +static IrInstSrc *astgen_container_decl(Stage1AstGen *ag, Scope *parent_scope, AstNode *node) { assert(node->type == NodeTypeContainerDecl); ContainerKind kind = node->data.container_decl.kind; @@ -7564,7 +7573,7 @@ static IrInstSrc *ir_gen_container_decl(Stage1AstGen *ag, Scope *parent_scope, A return ir_build_const_type(ag, parent_scope, node, container_type); } -static IrInstSrc *ir_gen_err_set_decl(Stage1AstGen *ag, Scope *parent_scope, AstNode *node) { +static IrInstSrc *astgen_err_set_decl(Stage1AstGen *ag, Scope *parent_scope, AstNode *node) { assert(node->type == NodeTypeErrorSetDecl); uint32_t err_count = node->data.err_set_decl.decls.length; @@ -7615,7 +7624,7 @@ static IrInstSrc *ir_gen_err_set_decl(Stage1AstGen *ag, Scope *parent_scope, Ast return ir_build_const_type(ag, parent_scope, node, err_set_type); } -static IrInstSrc *ir_gen_fn_proto(Stage1AstGen *ag, Scope *parent_scope, AstNode *node) { +static IrInstSrc *astgen_fn_proto(Stage1AstGen *ag, Scope *parent_scope, AstNode *node) { assert(node->type == NodeTypeFnProto); size_t param_count = node->data.fn_proto.params.length; @@ -7630,7 +7639,7 @@ static IrInstSrc *ir_gen_fn_proto(Stage1AstGen *ag, Scope *parent_scope, AstNode } if (param_node->data.param_decl.anytype_token == 0) { AstNode *type_node = param_node->data.param_decl.type; - IrInstSrc *type_value = ir_gen_node(ag, type_node, parent_scope); + IrInstSrc *type_value = astgen_node(ag, type_node, parent_scope); if (type_value == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; param_types[i] = type_value; @@ -7641,14 +7650,14 @@ static IrInstSrc *ir_gen_fn_proto(Stage1AstGen *ag, Scope *parent_scope, AstNode IrInstSrc *align_value = nullptr; if (node->data.fn_proto.align_expr != nullptr) { - align_value = ir_gen_node(ag, node->data.fn_proto.align_expr, parent_scope); + align_value = astgen_node(ag, node->data.fn_proto.align_expr, parent_scope); if (align_value == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; } IrInstSrc *callconv_value = nullptr; if (node->data.fn_proto.callconv_expr != nullptr) { - callconv_value = ir_gen_node(ag, node->data.fn_proto.callconv_expr, parent_scope); + callconv_value = astgen_node(ag, node->data.fn_proto.callconv_expr, parent_scope); if (callconv_value == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; } @@ -7657,7 +7666,7 @@ static IrInstSrc *ir_gen_fn_proto(Stage1AstGen *ag, Scope *parent_scope, AstNode if (node->data.fn_proto.return_type == nullptr) { return_type = ir_build_const_type(ag, parent_scope, node, ag->codegen->builtin_types.entry_void); } else { - return_type = ir_gen_node(ag, node->data.fn_proto.return_type, parent_scope); + return_type = astgen_node(ag, node->data.fn_proto.return_type, parent_scope); if (return_type == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; } @@ -7665,17 +7674,17 @@ static IrInstSrc *ir_gen_fn_proto(Stage1AstGen *ag, Scope *parent_scope, AstNode return ir_build_fn_proto(ag, parent_scope, node, param_types, align_value, callconv_value, return_type, is_var_args); } -static IrInstSrc *ir_gen_resume(Stage1AstGen *ag, Scope *scope, AstNode *node) { +static IrInstSrc *astgen_resume(Stage1AstGen *ag, Scope *scope, AstNode *node) { assert(node->type == NodeTypeResume); - IrInstSrc *target_inst = ir_gen_node_extra(ag, node->data.resume_expr.expr, scope, LValPtr, nullptr); + IrInstSrc *target_inst = astgen_node_extra(ag, node->data.resume_expr.expr, scope, LValPtr, nullptr); if (target_inst == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; return ir_build_resume_src(ag, scope, node, target_inst); } -static IrInstSrc *ir_gen_await_expr(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, +static IrInstSrc *astgen_await_expr(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypeAwaitExpr); @@ -7690,7 +7699,7 @@ static IrInstSrc *ir_gen_await_expr(Stage1AstGen *ag, Scope *scope, AstNode *nod if (entry != nullptr) { BuiltinFnEntry *builtin_fn = entry->value; if (builtin_fn->id == BuiltinFnIdAsyncCall) { - return ir_gen_async_call(ag, scope, node, expr_node, lval, result_loc); + return astgen_async_call(ag, scope, node, expr_node, lval, result_loc); } } } @@ -7709,7 +7718,7 @@ static IrInstSrc *ir_gen_await_expr(Stage1AstGen *ag, Scope *scope, AstNode *nod return ag->codegen->invalid_inst_src; } - IrInstSrc *target_inst = ir_gen_node_extra(ag, expr_node, scope, LValPtr, nullptr); + IrInstSrc *target_inst = astgen_node_extra(ag, expr_node, scope, LValPtr, nullptr); if (target_inst == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; @@ -7717,7 +7726,7 @@ static IrInstSrc *ir_gen_await_expr(Stage1AstGen *ag, Scope *scope, AstNode *nod return ir_lval_wrap(ag, scope, await_inst, lval, result_loc); } -static IrInstSrc *ir_gen_suspend(Stage1AstGen *ag, Scope *parent_scope, AstNode *node) { +static IrInstSrc *astgen_suspend(Stage1AstGen *ag, Scope *parent_scope, AstNode *node) { assert(node->type == NodeTypeSuspend); if (!ag->fn) { @@ -7742,7 +7751,7 @@ static IrInstSrc *ir_gen_suspend(Stage1AstGen *ag, Scope *parent_scope, AstNode IrInstSrcSuspendBegin *begin = ir_build_suspend_begin_src(ag, parent_scope, node); ScopeSuspend *suspend_scope = create_suspend_scope(ag->codegen, node, parent_scope); Scope *child_scope = &suspend_scope->base; - IrInstSrc *susp_res = ir_gen_node(ag, node->data.suspend.block, child_scope); + IrInstSrc *susp_res = astgen_node(ag, node->data.suspend.block, child_scope); if (susp_res == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; ir_mark_gen(ir_build_check_statement_is_void(ag, child_scope, node->data.suspend.block, susp_res)); @@ -7750,7 +7759,7 @@ static IrInstSrc *ir_gen_suspend(Stage1AstGen *ag, Scope *parent_scope, AstNode return ir_mark_gen(ir_build_suspend_finish_src(ag, parent_scope, node, begin)); } -static IrInstSrc *ir_gen_node_raw(Stage1AstGen *ag, AstNode *node, Scope *scope, +static IrInstSrc *astgen_node_raw(Stage1AstGen *ag, AstNode *node, Scope *scope, LVal lval, ResultLoc *result_loc) { assert(scope); @@ -7766,40 +7775,40 @@ static IrInstSrc *ir_gen_node_raw(Stage1AstGen *ag, AstNode *node, Scope *scope, case NodeTypeTestDecl: zig_unreachable(); case NodeTypeBlock: - return ir_gen_block(ag, scope, node, lval, result_loc); + return astgen_block(ag, scope, node, lval, result_loc); case NodeTypeGroupedExpr: - return ir_gen_node_raw(ag, node->data.grouped_expr, scope, lval, result_loc); + return astgen_node_raw(ag, node->data.grouped_expr, scope, lval, result_loc); case NodeTypeBinOpExpr: - return ir_gen_bin_op(ag, scope, node, lval, result_loc); + return astgen_bin_op(ag, scope, node, lval, result_loc); case NodeTypeIntLiteral: - return ir_lval_wrap(ag, scope, ir_gen_int_lit(ag, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_int_lit(ag, scope, node), lval, result_loc); case NodeTypeFloatLiteral: - return ir_lval_wrap(ag, scope, ir_gen_float_lit(ag, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_float_lit(ag, scope, node), lval, result_loc); case NodeTypeCharLiteral: - return ir_lval_wrap(ag, scope, ir_gen_char_lit(ag, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_char_lit(ag, scope, node), lval, result_loc); case NodeTypeIdentifier: - return ir_gen_symbol(ag, scope, node, lval, result_loc); + return astgen_identifier(ag, scope, node, lval, result_loc); case NodeTypeFnCallExpr: - return ir_gen_fn_call(ag, scope, node, lval, result_loc); + return astgen_fn_call(ag, scope, node, lval, result_loc); case NodeTypeIfBoolExpr: - return ir_gen_if_bool_expr(ag, scope, node, lval, result_loc); + return astgen_if_bool_expr(ag, scope, node, lval, result_loc); case NodeTypePrefixOpExpr: - return ir_gen_prefix_op_expr(ag, scope, node, lval, result_loc); + return astgen_prefix_op_expr(ag, scope, node, lval, result_loc); case NodeTypeContainerInitExpr: - return ir_gen_container_init_expr(ag, scope, node, lval, result_loc); + return astgen_container_init_expr(ag, scope, node, lval, result_loc); case NodeTypeVariableDeclaration: - return ir_gen_var_decl(ag, scope, node); + return astgen_var_decl(ag, scope, node); case NodeTypeWhileExpr: - return ir_gen_while_expr(ag, scope, node, lval, result_loc); + return astgen_while_expr(ag, scope, node, lval, result_loc); case NodeTypeForExpr: - return ir_gen_for_expr(ag, scope, node, lval, result_loc); + return astgen_for_expr(ag, scope, node, lval, result_loc); case NodeTypeArrayAccessExpr: - return ir_gen_array_access(ag, scope, node, lval, result_loc); + return astgen_array_access(ag, scope, node, lval, result_loc); case NodeTypeReturnExpr: - return ir_gen_return(ag, scope, node, lval, result_loc); + return astgen_return(ag, scope, node, lval, result_loc); case NodeTypeFieldAccessExpr: { - IrInstSrc *ptr_instruction = ir_gen_field_access(ag, scope, node); + IrInstSrc *ptr_instruction = astgen_field_access(ag, scope, node); if (ptr_instruction == ag->codegen->invalid_inst_src) return ptr_instruction; if (lval == LValPtr || lval == LValAssign) @@ -7815,7 +7824,7 @@ static IrInstSrc *ir_gen_node_raw(Stage1AstGen *ag, AstNode *node, Scope *scope, if (child_lval == LValAssign) child_lval = LValPtr; - IrInstSrc *value = ir_gen_node_extra(ag, expr_node, scope, child_lval, nullptr); + IrInstSrc *value = astgen_node_extra(ag, expr_node, scope, child_lval, nullptr); if (value == ag->codegen->invalid_inst_src) return value; @@ -7828,7 +7837,7 @@ static IrInstSrc *ir_gen_node_raw(Stage1AstGen *ag, AstNode *node, Scope *scope, case NodeTypeUnwrapOptional: { AstNode *expr_node = node->data.unwrap_optional.expr; - IrInstSrc *maybe_ptr = ir_gen_node_extra(ag, expr_node, scope, LValPtr, nullptr); + IrInstSrc *maybe_ptr = astgen_node_extra(ag, expr_node, scope, LValPtr, nullptr); if (maybe_ptr == ag->codegen->invalid_inst_src) return ag->codegen->invalid_inst_src; @@ -7840,59 +7849,59 @@ static IrInstSrc *ir_gen_node_raw(Stage1AstGen *ag, AstNode *node, Scope *scope, return ir_expr_wrap(ag, scope, load_ptr, result_loc); } case NodeTypeBoolLiteral: - return ir_lval_wrap(ag, scope, ir_gen_bool_literal(ag, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_bool_literal(ag, scope, node), lval, result_loc); case NodeTypeArrayType: - return ir_lval_wrap(ag, scope, ir_gen_array_type(ag, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_array_type(ag, scope, node), lval, result_loc); case NodeTypePointerType: - return ir_lval_wrap(ag, scope, ir_gen_pointer_type(ag, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_pointer_type(ag, scope, node), lval, result_loc); case NodeTypeAnyFrameType: - return ir_lval_wrap(ag, scope, ir_gen_anyframe_type(ag, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_anyframe_type(ag, scope, node), lval, result_loc); case NodeTypeStringLiteral: - return ir_lval_wrap(ag, scope, ir_gen_string_literal(ag, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_string_literal(ag, scope, node), lval, result_loc); case NodeTypeUndefinedLiteral: - return ir_lval_wrap(ag, scope, ir_gen_undefined_literal(ag, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_undefined_literal(ag, scope, node), lval, result_loc); case NodeTypeAsmExpr: - return ir_lval_wrap(ag, scope, ir_gen_asm_expr(ag, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_asm_expr(ag, scope, node), lval, result_loc); case NodeTypeNullLiteral: - return ir_lval_wrap(ag, scope, ir_gen_null_literal(ag, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_null_literal(ag, scope, node), lval, result_loc); case NodeTypeIfErrorExpr: - return ir_gen_if_err_expr(ag, scope, node, lval, result_loc); + return astgen_if_err_expr(ag, scope, node, lval, result_loc); case NodeTypeIfOptional: - return ir_gen_if_optional_expr(ag, scope, node, lval, result_loc); + return astgen_if_optional_expr(ag, scope, node, lval, result_loc); case NodeTypeSwitchExpr: - return ir_gen_switch_expr(ag, scope, node, lval, result_loc); + return astgen_switch_expr(ag, scope, node, lval, result_loc); case NodeTypeCompTime: - return ir_expr_wrap(ag, scope, ir_gen_comptime(ag, scope, node, lval), result_loc); + return ir_expr_wrap(ag, scope, astgen_comptime(ag, scope, node, lval), result_loc); case NodeTypeNoSuspend: - return ir_expr_wrap(ag, scope, ir_gen_nosuspend(ag, scope, node, lval), result_loc); + return ir_expr_wrap(ag, scope, astgen_nosuspend(ag, scope, node, lval), result_loc); case NodeTypeErrorType: - return ir_lval_wrap(ag, scope, ir_gen_error_type(ag, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_error_type(ag, scope, node), lval, result_loc); case NodeTypeBreak: - return ir_lval_wrap(ag, scope, ir_gen_break(ag, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_break(ag, scope, node), lval, result_loc); case NodeTypeContinue: - return ir_lval_wrap(ag, scope, ir_gen_continue(ag, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_continue(ag, scope, node), lval, result_loc); case NodeTypeUnreachable: return ir_build_unreachable(ag, scope, node); case NodeTypeDefer: - return ir_lval_wrap(ag, scope, ir_gen_defer(ag, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_defer(ag, scope, node), lval, result_loc); case NodeTypeSliceExpr: - return ir_gen_slice(ag, scope, node, lval, result_loc); + return astgen_slice(ag, scope, node, lval, result_loc); case NodeTypeCatchExpr: - return ir_gen_catch(ag, scope, node, lval, result_loc); + return astgen_catch(ag, scope, node, lval, result_loc); case NodeTypeContainerDecl: - return ir_lval_wrap(ag, scope, ir_gen_container_decl(ag, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_container_decl(ag, scope, node), lval, result_loc); case NodeTypeFnProto: - return ir_lval_wrap(ag, scope, ir_gen_fn_proto(ag, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_fn_proto(ag, scope, node), lval, result_loc); case NodeTypeErrorSetDecl: - return ir_lval_wrap(ag, scope, ir_gen_err_set_decl(ag, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_err_set_decl(ag, scope, node), lval, result_loc); case NodeTypeResume: - return ir_lval_wrap(ag, scope, ir_gen_resume(ag, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_resume(ag, scope, node), lval, result_loc); case NodeTypeAwaitExpr: - return ir_gen_await_expr(ag, scope, node, lval, result_loc); + return astgen_await_expr(ag, scope, node, lval, result_loc); case NodeTypeSuspend: - return ir_lval_wrap(ag, scope, ir_gen_suspend(ag, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_suspend(ag, scope, node), lval, result_loc); case NodeTypeEnumLiteral: - return ir_lval_wrap(ag, scope, ir_gen_enum_literal(ag, scope, node), lval, result_loc); + return ir_lval_wrap(ag, scope, astgen_enum_literal(ag, scope, node), lval, result_loc); case NodeTypeInferredArrayType: add_node_error(ag->codegen, node, buf_sprintf("inferred array size invalid here")); @@ -7910,7 +7919,7 @@ ResultLoc *no_result_loc(void) { return &result_loc_none->base; } -static IrInstSrc *ir_gen_node_extra(Stage1AstGen *ag, AstNode *node, Scope *scope, LVal lval, +static IrInstSrc *astgen_node_extra(Stage1AstGen *ag, AstNode *node, Scope *scope, LVal lval, ResultLoc *result_loc) { if (lval == LValAssign) { @@ -8018,7 +8027,7 @@ static IrInstSrc *ir_gen_node_extra(Stage1AstGen *ag, AstNode *node, Scope *scop } else { child_scope = &create_expr_scope(ag->codegen, node, scope)->base; } - IrInstSrc *result = ir_gen_node_raw(ag, node, child_scope, lval, result_loc); + IrInstSrc *result = astgen_node_raw(ag, node, child_scope, lval, result_loc); if (result == ag->codegen->invalid_inst_src) { if (ag->exec->first_err_trace_msg == nullptr) { ag->exec->first_err_trace_msg = ag->codegen->trace_err; @@ -8027,8 +8036,8 @@ static IrInstSrc *ir_gen_node_extra(Stage1AstGen *ag, AstNode *node, Scope *scop return result; } -static IrInstSrc *ir_gen_node(Stage1AstGen *ag, AstNode *node, Scope *scope) { - return ir_gen_node_extra(ag, node, scope, LValNone, nullptr); +static IrInstSrc *astgen_node(Stage1AstGen *ag, AstNode *node, Scope *scope) { + return astgen_node_extra(ag, node, scope, LValNone, nullptr); } bool stage1_astgen(CodeGen *codegen, AstNode *node, Scope *scope, Stage1Zir *stage1_zir, @@ -8050,7 +8059,7 @@ bool stage1_astgen(CodeGen *codegen, AstNode *node, Scope *scope, Stage1Zir *sta // Entry block gets a reference because we enter it to begin. ir_ref_bb(ag->current_basic_block); - IrInstSrc *result = ir_gen_node_extra(ag, node, scope, LValNone, nullptr); + IrInstSrc *result = astgen_node_extra(ag, node, scope, LValNone, nullptr); if (result == ag->codegen->invalid_inst_src) return false; diff --git a/src/stage1/parser.cpp b/src/stage1/parser.cpp index 51acc6a566..8cd624daad 100644 --- a/src/stage1/parser.cpp +++ b/src/stage1/parser.cpp @@ -202,6 +202,19 @@ static void put_back_token(ParseContext *pc) { pc->current_token -= 1; } +static Buf *token_string_literal_buf(RootStruct *root_struct, TokenIndex token) { + Error err; + assert(root_struct->token_ids[token] == TokenIdStringLiteral); + const char *source = buf_ptr(root_struct->source_code); + size_t byte_offset = root_struct->token_locs[token].offset; + size_t bad_index; + Buf *str = buf_alloc(); + if ((err = source_string_literal_buf(source + byte_offset, str, &bad_index))) { + zig_panic("TODO handle string literal parse error"); + } + return str; +} + static Buf *token_buf(ParseContext *pc, TokenIndex token) { if (token == 0) return nullptr; @@ -3465,19 +3478,6 @@ Error source_char_literal(const char *source, uint32_t *result, size_t *bad_inde } -Buf *token_string_literal_buf(RootStruct *root_struct, TokenIndex token) { - Error err; - assert(root_struct->token_ids[token] == TokenIdStringLiteral); - const char *source = buf_ptr(root_struct->source_code); - size_t byte_offset = root_struct->token_locs[token].offset; - size_t bad_index; - Buf *str = buf_alloc(); - if ((err = source_string_literal_buf(source + byte_offset, str, &bad_index))) { - zig_panic("TODO handle string literal parse error"); - } - return str; -} - Buf *token_identifier_buf(RootStruct *root_struct, TokenIndex token) { Error err; const char *source = buf_ptr(root_struct->source_code); @@ -3515,14 +3515,15 @@ Buf *token_identifier_buf(RootStruct *root_struct, TokenIndex token) { Buf *node_identifier_buf(AstNode *node) { assert(node->type == NodeTypeIdentifier); - RootStruct *root_struct = node->owner->data.structure.root_struct; - return token_identifier_buf(root_struct, node->main_token); -} - -Buf *node_string_literal_buf(AstNode *node) { - assert(node->type == NodeTypeStringLiteral); - RootStruct *root_struct = node->owner->data.structure.root_struct; - return token_string_literal_buf(root_struct, node->main_token); + // Currently, stage1 runs astgen for every comptime function call, + // resulting the allocation here wasting memory. As a workaround until + // the code is adjusted to make astgen run only once per source node, + // we memoize the result into the AST here. + if (node->data.identifier.name == nullptr) { + RootStruct *root_struct = node->owner->data.structure.root_struct; + node->data.identifier.name = token_identifier_buf(root_struct, node->main_token); + } + return node->data.identifier.name; } void token_number_literal_bigint(RootStruct *root_struct, BigInt *result, TokenIndex token) { diff --git a/src/stage1/parser.hpp b/src/stage1/parser.hpp index 2d9a5f0b4a..9f73444cb8 100644 --- a/src/stage1/parser.hpp +++ b/src/stage1/parser.hpp @@ -19,10 +19,8 @@ void ast_print(AstNode *node, int indent); void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *context), void *context); Buf *node_identifier_buf(AstNode *node); -Buf *node_string_literal_buf(AstNode *node); Buf *token_identifier_buf(RootStruct *root_struct, TokenIndex token); -Buf *token_string_literal_buf(RootStruct *root_struct, TokenIndex token); void token_number_literal_bigint(RootStruct *root_struct, BigInt *result, TokenIndex token); diff --git a/src/stage1/tokenizer.cpp b/src/stage1/tokenizer.cpp index 873a48b327..4550f32e8c 100644 --- a/src/stage1/tokenizer.cpp +++ b/src/stage1/tokenizer.cpp @@ -291,11 +291,11 @@ static void tokenize_error(Tokenize *t, const char *format, ...) { static void begin_token(Tokenize *t, TokenId id) { t->out->ids.append(id); - t->out->locs.append({ - .offset = (uint32_t) t->pos, - .line = t->line, - .column = t->column, - }); + TokenLoc tok_loc; + tok_loc.offset = (uint32_t) t->pos; + tok_loc.line = t->line; + tok_loc.column = t->column; + t->out->locs.append(tok_loc); } static void cancel_token(Tokenize *t) { From d888fa12a88ae7e5332de669b3c3a1dac57f5c19 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 28 May 2021 16:11:27 -0700 Subject: [PATCH 14/14] stage1 parser: fix the TODOs --- src/stage1/parser.cpp | 50 ++++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/src/stage1/parser.cpp b/src/stage1/parser.cpp index 8cd624daad..b28c68e063 100644 --- a/src/stage1/parser.cpp +++ b/src/stage1/parser.cpp @@ -126,6 +126,19 @@ static AstNode *ast_parse_container_decl_auto(ParseContext *pc); static AstNode *ast_parse_container_decl_type(ParseContext *pc); static AstNode *ast_parse_byte_align(ParseContext *pc); +ATTRIBUTE_NORETURN +static void ast_error_offset(RootStruct *root_struct, ErrColor err_color, + TokenIndex token, size_t bad_index, Buf *msg) +{ + assert(token < root_struct->token_count); + uint32_t byte_offset = root_struct->token_locs[token].offset; + ErrorMsg *err = err_msg_create_with_offset(root_struct->path, + byte_offset + bad_index, buf_ptr(root_struct->source_code), msg); + + print_err_msg(err, err_color); + exit(EXIT_FAILURE); +} + ATTRIBUTE_PRINTF(3, 4) ATTRIBUTE_NORETURN static void ast_error(ParseContext *pc, TokenIndex token, const char *format, ...) { @@ -135,13 +148,7 @@ static void ast_error(ParseContext *pc, TokenIndex token, const char *format, .. va_end(ap); RootStruct *root_struct = pc->owner->data.structure.root_struct; - assert(token < root_struct->token_count); - uint32_t byte_offset = root_struct->token_locs[token].offset; - ErrorMsg *err = err_msg_create_with_offset(root_struct->path, - byte_offset, buf_ptr(root_struct->source_code), msg); - - print_err_msg(err, pc->err_color); - exit(EXIT_FAILURE); + ast_error_offset(root_struct, pc->err_color, token, 0, msg); } ATTRIBUTE_NORETURN @@ -202,20 +209,9 @@ static void put_back_token(ParseContext *pc) { pc->current_token -= 1; } -static Buf *token_string_literal_buf(RootStruct *root_struct, TokenIndex token) { - Error err; - assert(root_struct->token_ids[token] == TokenIdStringLiteral); - const char *source = buf_ptr(root_struct->source_code); - size_t byte_offset = root_struct->token_locs[token].offset; - size_t bad_index; - Buf *str = buf_alloc(); - if ((err = source_string_literal_buf(source + byte_offset, str, &bad_index))) { - zig_panic("TODO handle string literal parse error"); - } - return str; -} - static Buf *token_buf(ParseContext *pc, TokenIndex token) { + Error err; + if (token == 0) return nullptr; @@ -223,7 +219,16 @@ static Buf *token_buf(ParseContext *pc, TokenIndex token) { if (root_struct->token_ids[token] == TokenIdIdentifier) { return token_identifier_buf(root_struct, token); } else if (root_struct->token_ids[token] == TokenIdStringLiteral) { - return token_string_literal_buf(root_struct, token); + assert(root_struct->token_ids[token] == TokenIdStringLiteral); + const char *source = buf_ptr(root_struct->source_code); + size_t byte_offset = root_struct->token_locs[token].offset; + size_t bad_index; + Buf *str = buf_alloc(); + if ((err = source_string_literal_buf(source + byte_offset, str, &bad_index))) { + ast_error_offset(root_struct, pc->err_color, token, bad_index, + buf_create_from_str("invalid string literal character")); + } + return str; } else { zig_unreachable(); } @@ -3493,7 +3498,8 @@ Buf *token_identifier_buf(RootStruct *root_struct, TokenIndex token) { size_t bad_index; Buf *str = buf_alloc(); if ((err = source_string_literal_buf(source + byte_offset + 1, str, &bad_index))) { - zig_panic("TODO handle string literal parse error"); + ast_error_offset(root_struct, ErrColorAuto, token, bad_index + 1, + buf_create_from_str("invalid string literal character")); } return str; } else {