astgen: add func_fancy, noalias_bits, varargs, and callconv support in fnDecl
Implement several interconnected features for function declarations: - noalias_bits: Track which parameters have the noalias keyword by setting corresponding bits in a uint32_t (supports up to 32 parameters) - is_var_args: Detect ellipsis3 (...) token in parameter list - is_noinline/has_inline_keyword: Detect noinline/inline modifiers - callconv handling: Extract callconv_expr from fn_proto variants, create cc_gz sub-block, emit builtin_value for explicit callconv() or inline - func_fancy instruction: When any of cc_ref, is_var_args, noalias_bits, or is_noinline are present, emit func_fancy instead of func/func_inferred with the appropriate FuncFancy payload layout - fn_var_args: Track in AstGenCtx for body code that checks it - BuiltinValue constants: Add all ZIR_BUILTIN_VALUE_* defines to zir.h - addBuiltinValue helper: Emit extended builtin_value instructions Generic tracking (any_param_used, ret_ty_is_generic, ret_body_param_refs) is not yet implemented as it requires is_used_or_discarded support in ScopeLocalVal scope lookups. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
252
astgen.c
252
astgen.c
@@ -114,6 +114,7 @@ typedef struct {
|
|||||||
uint32_t nodes_need_rl_cap;
|
uint32_t nodes_need_rl_cap;
|
||||||
bool has_compile_errors;
|
bool has_compile_errors;
|
||||||
bool within_fn; // AstGen.zig:49
|
bool within_fn; // AstGen.zig:49
|
||||||
|
bool fn_var_args; // AstGen.zig:46
|
||||||
} AstGenCtx;
|
} AstGenCtx;
|
||||||
|
|
||||||
static void setCompileError(AstGenCtx* ag, const char* where, int line) {
|
static void setCompileError(AstGenCtx* ag, const char* where, int line) {
|
||||||
@@ -575,6 +576,25 @@ static uint32_t addPlNodePayloadIndex(
|
|||||||
return addInstruction(gz, tag, data);
|
return addInstruction(gz, tag, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mirrors GenZir.addBuiltinValue (AstGen.zig:12389-12391).
|
||||||
|
// Emits extended instruction with builtin_value opcode.
|
||||||
|
static uint32_t addBuiltinValue(
|
||||||
|
GenZir* gz, uint32_t src_node, uint16_t builtin_val) {
|
||||||
|
AstGenCtx* ag = gz->astgen;
|
||||||
|
ensureInstCapacity(ag, 1);
|
||||||
|
uint32_t idx = ag->inst_len;
|
||||||
|
ag->inst_tags[idx] = ZIR_INST_EXTENDED;
|
||||||
|
ZirInstData data;
|
||||||
|
data.extended.opcode = (uint16_t)ZIR_EXT_BUILTIN_VALUE;
|
||||||
|
data.extended.small = builtin_val;
|
||||||
|
data.extended.operand
|
||||||
|
= (uint32_t)((int32_t)src_node - (int32_t)gz->decl_node_index);
|
||||||
|
ag->inst_datas[idx] = data;
|
||||||
|
ag->inst_len++;
|
||||||
|
gzAppendInstruction(gz, idx);
|
||||||
|
return idx + ZIR_REF_START_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
// --- Source cursor (AstGen.zig:13335-13359) ---
|
// --- Source cursor (AstGen.zig:13335-13359) ---
|
||||||
|
|
||||||
// Mirrors AstGen.advanceSourceCursor (AstGen.zig:13342).
|
// Mirrors AstGen.advanceSourceCursor (AstGen.zig:13342).
|
||||||
@@ -8386,6 +8406,123 @@ static uint32_t addFunc(GenZir* gz, uint32_t src_node, uint32_t block_node,
|
|||||||
return addInstruction(gz, tag, data);
|
return addInstruction(gz, tag, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- addFuncFancy (AstGen.zig:12112-12173) ---
|
||||||
|
// Emits func_fancy instruction when cc_ref, is_var_args, noalias_bits,
|
||||||
|
// or is_noinline are present.
|
||||||
|
|
||||||
|
static uint32_t addFuncFancy(GenZir* gz, uint32_t src_node,
|
||||||
|
uint32_t block_node, uint32_t param_block, uint32_t ret_ref,
|
||||||
|
const uint32_t* ret_body, uint32_t ret_body_len, uint32_t cc_ref,
|
||||||
|
const uint32_t* cc_body, uint32_t cc_body_len, const uint32_t* body,
|
||||||
|
uint32_t body_len, const uint32_t* param_insts, uint32_t param_insts_len,
|
||||||
|
uint32_t lbrace_line, uint32_t lbrace_column, bool is_var_args,
|
||||||
|
bool is_inferred_error, bool is_noinline, uint32_t noalias_bits) {
|
||||||
|
AstGenCtx* ag = gz->astgen;
|
||||||
|
const Ast* tree = ag->tree;
|
||||||
|
uint32_t rbrace_tok = lastToken(tree, block_node);
|
||||||
|
uint32_t rbrace_start = tree->tokens.starts[rbrace_tok];
|
||||||
|
advanceSourceCursor(ag, rbrace_start);
|
||||||
|
uint32_t rbrace_line = ag->source_line - gz->decl_line;
|
||||||
|
uint32_t rbrace_column = ag->source_column;
|
||||||
|
|
||||||
|
uint32_t fixup_body_len = countBodyLenAfterFixupsExtraRefs(
|
||||||
|
ag, body, body_len, param_insts, param_insts_len);
|
||||||
|
|
||||||
|
// Calculate cc extra len (AstGen.zig:12231-12236).
|
||||||
|
uint32_t cc_extra_len = 0;
|
||||||
|
if (cc_body_len > 0) {
|
||||||
|
cc_extra_len = countBodyLenAfterFixups(ag, cc_body, cc_body_len) + 1;
|
||||||
|
} else if (cc_ref != ZIR_REF_NONE) {
|
||||||
|
cc_extra_len = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate ret extra len (AstGen.zig:12231-12236).
|
||||||
|
// Note: ret_param_refs are empty (no generic tracking yet).
|
||||||
|
uint32_t ret_extra_len = 0;
|
||||||
|
if (ret_body_len > 0) {
|
||||||
|
ret_extra_len
|
||||||
|
= countBodyLenAfterFixups(ag, ret_body, ret_body_len) + 1;
|
||||||
|
} else if (ret_ref != ZIR_REF_NONE) {
|
||||||
|
ret_extra_len = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FuncFancy has 3 fields: param_block, body_len, bits.
|
||||||
|
uint32_t total_extra = 3 + cc_extra_len + ret_extra_len
|
||||||
|
+ ((noalias_bits != 0) ? 1u : 0u) + fixup_body_len + 7;
|
||||||
|
ensureExtraCapacity(ag, total_extra);
|
||||||
|
|
||||||
|
// FuncFancy payload (Zir.zig:2589-2610).
|
||||||
|
uint32_t payload_index = ag->extra_len;
|
||||||
|
ag->extra[ag->extra_len++] = param_block;
|
||||||
|
ag->extra[ag->extra_len++] = fixup_body_len;
|
||||||
|
// Bits packed as u32 (Zir.zig:2598-2609).
|
||||||
|
uint32_t bits = 0;
|
||||||
|
if (is_var_args)
|
||||||
|
bits |= (1u << 0);
|
||||||
|
if (is_inferred_error)
|
||||||
|
bits |= (1u << 1);
|
||||||
|
if (is_noinline)
|
||||||
|
bits |= (1u << 2);
|
||||||
|
if (cc_ref != ZIR_REF_NONE)
|
||||||
|
bits |= (1u << 3); // has_cc_ref
|
||||||
|
if (cc_body_len > 0)
|
||||||
|
bits |= (1u << 4); // has_cc_body
|
||||||
|
if (ret_ref != ZIR_REF_NONE)
|
||||||
|
bits |= (1u << 5); // has_ret_ty_ref
|
||||||
|
if (ret_body_len > 0)
|
||||||
|
bits |= (1u << 6); // has_ret_ty_body
|
||||||
|
if (noalias_bits != 0)
|
||||||
|
bits |= (1u << 7); // has_any_noalias
|
||||||
|
// bit 8 = ret_ty_is_generic (false for now, no generic tracking)
|
||||||
|
ag->extra[ag->extra_len++] = bits;
|
||||||
|
|
||||||
|
// Trailing cc (AstGen.zig:12143-12151).
|
||||||
|
if (cc_body_len > 0) {
|
||||||
|
ag->extra[ag->extra_len++]
|
||||||
|
= countBodyLenAfterFixups(ag, cc_body, cc_body_len);
|
||||||
|
for (uint32_t i = 0; i < cc_body_len; i++)
|
||||||
|
appendPossiblyRefdBodyInst(ag, cc_body[i]);
|
||||||
|
} else if (cc_ref != ZIR_REF_NONE) {
|
||||||
|
ag->extra[ag->extra_len++] = cc_ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trailing ret_ty (AstGen.zig:12152-12164).
|
||||||
|
// Note: no ret_param_refs (generic tracking not implemented).
|
||||||
|
if (ret_body_len > 0) {
|
||||||
|
ag->extra[ag->extra_len++]
|
||||||
|
= countBodyLenAfterFixups(ag, ret_body, ret_body_len);
|
||||||
|
for (uint32_t i = 0; i < ret_body_len; i++)
|
||||||
|
appendPossiblyRefdBodyInst(ag, ret_body[i]);
|
||||||
|
} else if (ret_ref != ZIR_REF_NONE) {
|
||||||
|
ag->extra[ag->extra_len++] = ret_ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trailing noalias_bits (AstGen.zig:12166-12168).
|
||||||
|
if (noalias_bits != 0)
|
||||||
|
ag->extra[ag->extra_len++] = noalias_bits;
|
||||||
|
|
||||||
|
// Body (AstGen.zig:12170).
|
||||||
|
appendBodyWithFixupsExtraRefs(
|
||||||
|
ag, body, body_len, param_insts, param_insts_len);
|
||||||
|
|
||||||
|
// SrcLocs (AstGen.zig:12098-12106).
|
||||||
|
uint32_t columns = (lbrace_column & 0xFFFFu) | (rbrace_column << 16);
|
||||||
|
ag->extra[ag->extra_len++] = lbrace_line;
|
||||||
|
ag->extra[ag->extra_len++] = rbrace_line;
|
||||||
|
ag->extra[ag->extra_len++] = columns;
|
||||||
|
// proto_hash (4 words): zero for now.
|
||||||
|
ag->extra[ag->extra_len++] = 0;
|
||||||
|
ag->extra[ag->extra_len++] = 0;
|
||||||
|
ag->extra[ag->extra_len++] = 0;
|
||||||
|
ag->extra[ag->extra_len++] = 0;
|
||||||
|
|
||||||
|
// Emit the func_fancy instruction (AstGen.zig:12220-12226).
|
||||||
|
ZirInstData data;
|
||||||
|
data.pl_node.src_node = (int32_t)src_node - (int32_t)gz->decl_node_index;
|
||||||
|
data.pl_node.payload_index = payload_index;
|
||||||
|
return addInstruction(gz, ZIR_INST_FUNC_FANCY, data);
|
||||||
|
}
|
||||||
|
|
||||||
// --- testDecl (AstGen.zig:4708) ---
|
// --- testDecl (AstGen.zig:4708) ---
|
||||||
|
|
||||||
static void testDecl(AstGenCtx* ag, GenZir* gz, uint32_t* wip_decl_insts,
|
static void testDecl(AstGenCtx* ag, GenZir* gz, uint32_t* wip_decl_insts,
|
||||||
@@ -8541,10 +8678,12 @@ static void fnDecl(AstGenCtx* ag, GenZir* gz, uint32_t* wip_decl_insts,
|
|||||||
uint32_t fn_token = tree->nodes.main_tokens[proto_node];
|
uint32_t fn_token = tree->nodes.main_tokens[proto_node];
|
||||||
uint32_t fn_name_token = fn_token + 1;
|
uint32_t fn_name_token = fn_token + 1;
|
||||||
|
|
||||||
// Check for 'pub', 'export' modifiers (Ast.zig:2003-2025,
|
// Check for 'pub', 'export', 'inline', 'noinline' modifiers
|
||||||
// AstGen.zig:4102-4106).
|
// (Ast.zig:2003-2025, AstGen.zig:4102-4106, 4240-4247).
|
||||||
bool is_pub = false;
|
bool is_pub = false;
|
||||||
bool is_export = false;
|
bool is_export = false;
|
||||||
|
bool is_noinline = false;
|
||||||
|
bool has_inline_keyword = false;
|
||||||
for (uint32_t i = fn_token; i > 0;) {
|
for (uint32_t i = fn_token; i > 0;) {
|
||||||
i--;
|
i--;
|
||||||
uint32_t ttag = tree->tokens.tags[i];
|
uint32_t ttag = tree->tokens.tags[i];
|
||||||
@@ -8552,6 +8691,10 @@ static void fnDecl(AstGenCtx* ag, GenZir* gz, uint32_t* wip_decl_insts,
|
|||||||
is_pub = true;
|
is_pub = true;
|
||||||
else if (ttag == TOKEN_KEYWORD_EXPORT)
|
else if (ttag == TOKEN_KEYWORD_EXPORT)
|
||||||
is_export = true;
|
is_export = true;
|
||||||
|
else if (ttag == TOKEN_KEYWORD_NOINLINE)
|
||||||
|
is_noinline = true;
|
||||||
|
else if (ttag == TOKEN_KEYWORD_INLINE)
|
||||||
|
has_inline_keyword = true;
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -8594,13 +8737,16 @@ static void fnDecl(AstGenCtx* ag, GenZir* gz, uint32_t* wip_decl_insts,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract param type nodes from proto variant (AstGen.zig:4253-4254).
|
// Extract param type nodes and callconv_expr from proto variant
|
||||||
|
// (AstGen.zig:4253-4254, Ast.zig:1456-1520).
|
||||||
uint32_t param_nodes_buf[1]; // buffer for fn_proto_simple/fn_proto_one
|
uint32_t param_nodes_buf[1]; // buffer for fn_proto_simple/fn_proto_one
|
||||||
const uint32_t* param_nodes = NULL;
|
const uint32_t* param_nodes = NULL;
|
||||||
uint32_t params_len = 0;
|
uint32_t params_len = 0;
|
||||||
|
uint32_t callconv_expr_node = 0; // 0 = none (OptionalIndex)
|
||||||
|
|
||||||
if (proto_tag == AST_NODE_FN_PROTO_SIMPLE) {
|
if (proto_tag == AST_NODE_FN_PROTO_SIMPLE) {
|
||||||
// data.lhs = optional param node, data.rhs = return type.
|
// data.lhs = optional param node, data.rhs = return type.
|
||||||
|
// callconv_expr = .none (Ast.zig:1468).
|
||||||
if (proto_data.lhs != 0) {
|
if (proto_data.lhs != 0) {
|
||||||
param_nodes_buf[0] = proto_data.lhs;
|
param_nodes_buf[0] = proto_data.lhs;
|
||||||
param_nodes = param_nodes_buf;
|
param_nodes = param_nodes_buf;
|
||||||
@@ -8616,8 +8762,11 @@ static void fnDecl(AstGenCtx* ag, GenZir* gz, uint32_t* wip_decl_insts,
|
|||||||
param_nodes = param_nodes_buf;
|
param_nodes = param_nodes_buf;
|
||||||
params_len = 1;
|
params_len = 1;
|
||||||
}
|
}
|
||||||
|
// AstFnProtoOne.callconv_expr at offset 4 (Ast.zig:4076).
|
||||||
|
callconv_expr_node = tree->extra_data.arr[extra_idx + 4];
|
||||||
} else if (proto_tag == AST_NODE_FN_PROTO_MULTI) {
|
} else if (proto_tag == AST_NODE_FN_PROTO_MULTI) {
|
||||||
// data.lhs = extra_data index → SubRange{start, end}.
|
// data.lhs = extra_data index → SubRange{start, end}.
|
||||||
|
// callconv_expr = .none (Ast.zig:1484).
|
||||||
uint32_t extra_idx = proto_data.lhs;
|
uint32_t extra_idx = proto_data.lhs;
|
||||||
uint32_t range_start = tree->extra_data.arr[extra_idx];
|
uint32_t range_start = tree->extra_data.arr[extra_idx];
|
||||||
uint32_t range_end = tree->extra_data.arr[extra_idx + 1];
|
uint32_t range_end = tree->extra_data.arr[extra_idx + 1];
|
||||||
@@ -8631,6 +8780,8 @@ static void fnDecl(AstGenCtx* ag, GenZir* gz, uint32_t* wip_decl_insts,
|
|||||||
uint32_t pend = tree->extra_data.arr[extra_idx + 1]; // params_end
|
uint32_t pend = tree->extra_data.arr[extra_idx + 1]; // params_end
|
||||||
param_nodes = tree->extra_data.arr + pstart;
|
param_nodes = tree->extra_data.arr + pstart;
|
||||||
params_len = pend - pstart;
|
params_len = pend - pstart;
|
||||||
|
// AstFnProto.callconv_expr at offset 5 (Ast.zig:4089).
|
||||||
|
callconv_expr_node = tree->extra_data.arr[extra_idx + 5];
|
||||||
}
|
}
|
||||||
|
|
||||||
// decl_gz (called value_gz in caller, decl_gz in fnDeclInner)
|
// decl_gz (called value_gz in caller, decl_gz in fnDeclInner)
|
||||||
@@ -8656,6 +8807,10 @@ static void fnDecl(AstGenCtx* ag, GenZir* gz, uint32_t* wip_decl_insts,
|
|||||||
// Collect param instruction indices (AstGen.zig:4254, 4360).
|
// Collect param instruction indices (AstGen.zig:4254, 4360).
|
||||||
uint32_t param_insts[32];
|
uint32_t param_insts[32];
|
||||||
uint32_t param_insts_len = 0;
|
uint32_t param_insts_len = 0;
|
||||||
|
// noalias_bits tracking (AstGen.zig:4259).
|
||||||
|
uint32_t noalias_bits = 0;
|
||||||
|
// is_var_args detection (AstGen.zig:4261).
|
||||||
|
bool is_var_args = false;
|
||||||
|
|
||||||
// Parameter iteration using token-based iterator, mirroring upstream
|
// Parameter iteration using token-based iterator, mirroring upstream
|
||||||
// FnProto.Iterator (Ast.zig:2680-2768, AstGen.zig:4260-4363).
|
// FnProto.Iterator (Ast.zig:2680-2768, AstGen.zig:4260-4363).
|
||||||
@@ -8670,6 +8825,7 @@ static void fnDecl(AstGenCtx* ag, GenZir* gz, uint32_t* wip_decl_insts,
|
|||||||
.src_node = 0,
|
.src_node = 0,
|
||||||
.ctx = RI_CTX_NONE };
|
.ctx = RI_CTX_NONE };
|
||||||
|
|
||||||
|
uint32_t param_type_i = 0; // index for noalias_bits (AstGen.zig:4262)
|
||||||
while (true) {
|
while (true) {
|
||||||
uint32_t name_token = 0;
|
uint32_t name_token = 0;
|
||||||
uint32_t comptime_noalias_token = 0;
|
uint32_t comptime_noalias_token = 0;
|
||||||
@@ -8717,9 +8873,11 @@ static void fnDecl(AstGenCtx* ag, GenZir* gz, uint32_t* wip_decl_insts,
|
|||||||
// Skip doc comments.
|
// Skip doc comments.
|
||||||
while (tree->tokens.tags[iter_tok_i] == TOKEN_DOC_COMMENT)
|
while (tree->tokens.tags[iter_tok_i] == TOKEN_DOC_COMMENT)
|
||||||
iter_tok_i++;
|
iter_tok_i++;
|
||||||
// Check for ellipsis3 (varargs) - skip for now.
|
// Check for ellipsis3 (varargs) (AstGen.zig:4275-4281).
|
||||||
if (tree->tokens.tags[iter_tok_i] == TOKEN_ELLIPSIS3)
|
if (tree->tokens.tags[iter_tok_i] == TOKEN_ELLIPSIS3) {
|
||||||
|
is_var_args = true;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
// Check for comptime/noalias prefix.
|
// Check for comptime/noalias prefix.
|
||||||
if (tree->tokens.tags[iter_tok_i] == TOKEN_KEYWORD_COMPTIME
|
if (tree->tokens.tags[iter_tok_i] == TOKEN_KEYWORD_COMPTIME
|
||||||
|| tree->tokens.tags[iter_tok_i] == TOKEN_KEYWORD_NOALIAS) {
|
|| tree->tokens.tags[iter_tok_i] == TOKEN_KEYWORD_NOALIAS) {
|
||||||
@@ -8743,8 +8901,15 @@ static void fnDecl(AstGenCtx* ag, GenZir* gz, uint32_t* wip_decl_insts,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine is_comptime from comptime_noalias token
|
// Determine is_comptime and noalias from comptime_noalias token
|
||||||
// (AstGen.zig:4265-4273).
|
// (AstGen.zig:4265-4273).
|
||||||
|
if (comptime_noalias_token != 0
|
||||||
|
&& tree->tokens.tags[comptime_noalias_token]
|
||||||
|
== TOKEN_KEYWORD_NOALIAS) {
|
||||||
|
// Track noalias_bits (AstGen.zig:4266-4269).
|
||||||
|
if (param_type_i < 32)
|
||||||
|
noalias_bits |= (1u << param_type_i);
|
||||||
|
}
|
||||||
if (comptime_noalias_token != 0
|
if (comptime_noalias_token != 0
|
||||||
&& tree->tokens.tags[comptime_noalias_token]
|
&& tree->tokens.tags[comptime_noalias_token]
|
||||||
== TOKEN_KEYWORD_COMPTIME) {
|
== TOKEN_KEYWORD_COMPTIME) {
|
||||||
@@ -8827,6 +8992,7 @@ static void fnDecl(AstGenCtx* ag, GenZir* gz, uint32_t* wip_decl_insts,
|
|||||||
lv->name = param_name_str;
|
lv->name = param_name_str;
|
||||||
params_scope = &lv->base;
|
params_scope = &lv->base;
|
||||||
}
|
}
|
||||||
|
param_type_i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Return type (AstGen.zig:4369-4383) ---
|
// --- Return type (AstGen.zig:4369-4383) ---
|
||||||
@@ -8866,6 +9032,46 @@ static void fnDecl(AstGenCtx* ag, GenZir* gz, uint32_t* wip_decl_insts,
|
|||||||
ag->source_line = saved_source_line;
|
ag->source_line = saved_source_line;
|
||||||
ag->source_column = saved_source_column;
|
ag->source_column = saved_source_column;
|
||||||
|
|
||||||
|
// --- Calling convention (AstGen.zig:4390-4413) ---
|
||||||
|
// Note: cc_gz uses `scope` (= &decl_gz.base), not params_scope.
|
||||||
|
GenZir cc_gz = makeSubBlock(&decl_gz, &decl_gz.base);
|
||||||
|
uint32_t cc_ref = ZIR_REF_NONE;
|
||||||
|
if (callconv_expr_node != 0) {
|
||||||
|
// Explicit callconv(expr) (AstGen.zig:4393-4405).
|
||||||
|
uint32_t cc_ty = addBuiltinValue(
|
||||||
|
&cc_gz, callconv_expr_node, ZIR_BUILTIN_VALUE_CALLING_CONVENTION);
|
||||||
|
ResultLoc cc_ri = { .tag = RL_COERCED_TY,
|
||||||
|
.data = cc_ty,
|
||||||
|
.src_node = 0,
|
||||||
|
.ctx = RI_CTX_NONE };
|
||||||
|
cc_ref = exprRl(&cc_gz, &decl_gz.base, cc_ri, callconv_expr_node);
|
||||||
|
if (ag->has_compile_errors) {
|
||||||
|
free(ret_body);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (gzInstructionsLen(&cc_gz) > 0) {
|
||||||
|
// break_inline targets the func instruction (patched later).
|
||||||
|
makeBreakInline(&cc_gz, 0, cc_ref, AST_NODE_OFFSET_NONE);
|
||||||
|
}
|
||||||
|
} else if (has_inline_keyword) {
|
||||||
|
// inline keyword → calling_convention_inline
|
||||||
|
// (AstGen.zig:4406-4409).
|
||||||
|
cc_ref = addBuiltinValue(
|
||||||
|
&cc_gz, node, ZIR_BUILTIN_VALUE_CALLING_CONVENTION_INLINE);
|
||||||
|
makeBreakInline(&cc_gz, 0, cc_ref, AST_NODE_OFFSET_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t cc_body_len = gzInstructionsLen(&cc_gz);
|
||||||
|
uint32_t* cc_body = NULL;
|
||||||
|
if (cc_body_len > 0) {
|
||||||
|
cc_body = malloc(cc_body_len * sizeof(uint32_t));
|
||||||
|
if (!cc_body)
|
||||||
|
abort();
|
||||||
|
memcpy(cc_body, gzInstructionsSlice(&cc_gz),
|
||||||
|
cc_body_len * sizeof(uint32_t));
|
||||||
|
}
|
||||||
|
gzUnstack(&cc_gz);
|
||||||
|
|
||||||
// --- Body (AstGen.zig:4415-4424) ---
|
// --- Body (AstGen.zig:4415-4424) ---
|
||||||
GenZir body_gz;
|
GenZir body_gz;
|
||||||
memset(&body_gz, 0, sizeof(body_gz));
|
memset(&body_gz, 0, sizeof(body_gz));
|
||||||
@@ -8878,10 +9084,13 @@ static void fnDecl(AstGenCtx* ag, GenZir* gz, uint32_t* wip_decl_insts,
|
|||||||
body_gz.instructions_top = ag->scratch_inst_len;
|
body_gz.instructions_top = ag->scratch_inst_len;
|
||||||
body_gz.any_defer_node = UINT32_MAX;
|
body_gz.any_defer_node = UINT32_MAX;
|
||||||
|
|
||||||
// Set fn_block and fn_ret_ty for the body (AstGen.zig:4442-4455).
|
// Set fn_block, fn_ret_ty, fn_var_args for the body
|
||||||
|
// (AstGen.zig:4442-4459).
|
||||||
void* prev_fn_block = ag->fn_block;
|
void* prev_fn_block = ag->fn_block;
|
||||||
setFnBlock(ag, &body_gz);
|
setFnBlock(ag, &body_gz);
|
||||||
uint32_t prev_fn_ret_ty = ag->fn_ret_ty;
|
uint32_t prev_fn_ret_ty = ag->fn_ret_ty;
|
||||||
|
bool prev_fn_var_args = ag->fn_var_args;
|
||||||
|
ag->fn_var_args = is_var_args;
|
||||||
if (is_inferred_error || ret_ref == ZIR_REF_NONE) {
|
if (is_inferred_error || ret_ref == ZIR_REF_NONE) {
|
||||||
// Non-void non-trivial return type: emit ret_type instruction.
|
// Non-void non-trivial return type: emit ret_type instruction.
|
||||||
if (ret_body_len > 0 || is_inferred_error) {
|
if (ret_body_len > 0 || is_inferred_error) {
|
||||||
@@ -8917,9 +9126,11 @@ static void fnDecl(AstGenCtx* ag, GenZir* gz, uint32_t* wip_decl_insts,
|
|||||||
ag->within_fn = prev_within_fn;
|
ag->within_fn = prev_within_fn;
|
||||||
ag->fn_block = prev_fn_block;
|
ag->fn_block = prev_fn_block;
|
||||||
ag->fn_ret_ty = prev_fn_ret_ty;
|
ag->fn_ret_ty = prev_fn_ret_ty;
|
||||||
|
ag->fn_var_args = prev_fn_var_args;
|
||||||
|
|
||||||
if (ag->has_compile_errors) {
|
if (ag->has_compile_errors) {
|
||||||
free(ret_body);
|
free(ret_body);
|
||||||
|
free(cc_body);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -8945,22 +9156,41 @@ static void fnDecl(AstGenCtx* ag, GenZir* gz, uint32_t* wip_decl_insts,
|
|||||||
uint32_t fn_body_len = gzInstructionsLen(&body_gz);
|
uint32_t fn_body_len = gzInstructionsLen(&body_gz);
|
||||||
gzUnstack(&body_gz);
|
gzUnstack(&body_gz);
|
||||||
|
|
||||||
// Create func instruction (AstGen.zig:4476-4494).
|
// Create func/func_fancy instruction (AstGen.zig:4476-4494,
|
||||||
uint32_t func_ref = addFunc(&decl_gz, node, body_node, decl_inst, ret_ref,
|
// 12112-12173).
|
||||||
|
bool need_fancy = cc_ref != ZIR_REF_NONE || is_var_args
|
||||||
|
|| noalias_bits != 0 || is_noinline;
|
||||||
|
uint32_t func_ref;
|
||||||
|
if (need_fancy) {
|
||||||
|
func_ref = addFuncFancy(&decl_gz, node, body_node, decl_inst, ret_ref,
|
||||||
|
ret_body, ret_body_len, cc_ref, cc_body, cc_body_len, fn_body,
|
||||||
|
fn_body_len, param_insts, param_insts_len, lbrace_line,
|
||||||
|
lbrace_column, is_var_args, is_inferred_error, is_noinline,
|
||||||
|
noalias_bits);
|
||||||
|
} else {
|
||||||
|
func_ref = addFunc(&decl_gz, node, body_node, decl_inst, ret_ref,
|
||||||
ret_body, ret_body_len, fn_body, fn_body_len, param_insts,
|
ret_body, ret_body_len, fn_body, fn_body_len, param_insts,
|
||||||
param_insts_len, lbrace_line, lbrace_column, is_inferred_error);
|
param_insts_len, lbrace_line, lbrace_column, is_inferred_error);
|
||||||
|
}
|
||||||
|
|
||||||
// Patch ret_body break_inline to point to func instruction
|
// Patch ret_body break_inline to point to func instruction
|
||||||
// (AstGen.zig:12199-12202).
|
// (AstGen.zig:12199-12202).
|
||||||
if (ret_body_len > 0) {
|
if (ret_body_len > 0) {
|
||||||
uint32_t break_inst = ret_body[ret_body_len - 1];
|
uint32_t break_inst = ret_body[ret_body_len - 1];
|
||||||
// The break_inline payload is at payload_index; block_inst is at
|
uint32_t break_payload
|
||||||
// offset 1 in the Break struct.
|
= ag->inst_datas[break_inst].break_data.payload_index;
|
||||||
|
ag->extra[break_payload + 1] = func_ref - ZIR_REF_START_INDEX;
|
||||||
|
}
|
||||||
|
// Patch cc_body break_inline to point to func instruction
|
||||||
|
// (AstGen.zig:12146-12148).
|
||||||
|
if (cc_body_len > 0) {
|
||||||
|
uint32_t break_inst = cc_body[cc_body_len - 1];
|
||||||
uint32_t break_payload
|
uint32_t break_payload
|
||||||
= ag->inst_datas[break_inst].break_data.payload_index;
|
= ag->inst_datas[break_inst].break_data.payload_index;
|
||||||
ag->extra[break_payload + 1] = func_ref - ZIR_REF_START_INDEX;
|
ag->extra[break_payload + 1] = func_ref - ZIR_REF_START_INDEX;
|
||||||
}
|
}
|
||||||
free(ret_body);
|
free(ret_body);
|
||||||
|
free(cc_body);
|
||||||
|
|
||||||
// break_inline returning func to declaration (AstGen.zig:4495).
|
// break_inline returning func to declaration (AstGen.zig:4495).
|
||||||
// nodeIndexToRelative(decl_node) = node - decl_gz.decl_node_index.
|
// nodeIndexToRelative(decl_node) = node - decl_gz.decl_node_index.
|
||||||
|
|||||||
17
zir.h
17
zir.h
@@ -513,6 +513,23 @@ typedef union {
|
|||||||
#define ZIR_REF_BOOL_FALSE 122
|
#define ZIR_REF_BOOL_FALSE 122
|
||||||
#define ZIR_REF_EMPTY_TUPLE 123
|
#define ZIR_REF_EMPTY_TUPLE 123
|
||||||
|
|
||||||
|
// Zir.Inst.BuiltinValue enum (Zir.zig:3476-3494).
|
||||||
|
#define ZIR_BUILTIN_VALUE_ATOMIC_ORDER 0
|
||||||
|
#define ZIR_BUILTIN_VALUE_ATOMIC_RMW_OP 1
|
||||||
|
#define ZIR_BUILTIN_VALUE_CALLING_CONVENTION 2
|
||||||
|
#define ZIR_BUILTIN_VALUE_ADDRESS_SPACE 3
|
||||||
|
#define ZIR_BUILTIN_VALUE_FLOAT_MODE 4
|
||||||
|
#define ZIR_BUILTIN_VALUE_REDUCE_OP 5
|
||||||
|
#define ZIR_BUILTIN_VALUE_CALL_MODIFIER 6
|
||||||
|
#define ZIR_BUILTIN_VALUE_PREFETCH_OPTIONS 7
|
||||||
|
#define ZIR_BUILTIN_VALUE_EXPORT_OPTIONS 8
|
||||||
|
#define ZIR_BUILTIN_VALUE_EXTERN_OPTIONS 9
|
||||||
|
#define ZIR_BUILTIN_VALUE_TYPE_INFO 10
|
||||||
|
#define ZIR_BUILTIN_VALUE_BRANCH_HINT 11
|
||||||
|
#define ZIR_BUILTIN_VALUE_CLOBBERS 12
|
||||||
|
#define ZIR_BUILTIN_VALUE_CALLING_CONVENTION_C 13
|
||||||
|
#define ZIR_BUILTIN_VALUE_CALLING_CONVENTION_INLINE 14
|
||||||
|
|
||||||
// Ast.Node.OptionalOffset.none = maxInt(i32).
|
// Ast.Node.OptionalOffset.none = maxInt(i32).
|
||||||
#define AST_NODE_OFFSET_NONE ((int32_t)0x7FFFFFFF)
|
#define AST_NODE_OFFSET_NONE ((int32_t)0x7FFFFFFF)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user