diff options
| author | Andrew Kelley <superjoe30@gmail.com> | 2017-08-30 00:46:38 -0400 |
|---|---|---|
| committer | Andrew Kelley <superjoe30@gmail.com> | 2017-08-30 00:46:38 -0400 |
| commit | fa9006f8d1aa95934f31d5bedfcd3949267c9e72 (patch) | |
| tree | 7551d28d4ee45e3ae5c6ebe73dd6979abe2b55ac /src/analyze.cpp | |
| parent | c2357830b4350a4685f867566afd79eaf2cb3c66 (diff) | |
| download | zig-fa9006f8d1aa95934f31d5bedfcd3949267c9e72.tar.gz zig-fa9006f8d1aa95934f31d5bedfcd3949267c9e72.zip | |
generic functions can access comptime args in align value
See #37
Diffstat (limited to 'src/analyze.cpp')
| -rw-r--r-- | src/analyze.cpp | 58 |
1 files changed, 27 insertions, 31 deletions
diff --git a/src/analyze.cpp b/src/analyze.cpp index 6adf4b3d51..17a25b9755 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -1061,13 +1061,31 @@ void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_cou fn_type_id->is_var_args = fn_proto->is_var_args; } -static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_scope, uint32_t alignment) { +static bool analyze_const_align(CodeGen *g, Scope *scope, AstNode *node, uint32_t *result) { + IrInstruction *align_result = analyze_const_value(g, scope, node, get_align_amt_type(g), nullptr); + if (type_is_invalid(align_result->value.type)) + return false; + + uint32_t align_bytes = bigint_as_unsigned(&align_result->value.data.x_bigint); + if (align_bytes == 0) { + add_node_error(g, node, buf_sprintf("alignment must be >= 1")); + return false; + } + if (!is_power_of_2(align_bytes)) { + add_node_error(g, node, buf_sprintf("alignment value %" PRIu32 " is not a power of 2", align_bytes)); + return false; + } + + *result = align_bytes; + return true; +} + +static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_scope) { assert(proto_node->type == NodeTypeFnProto); AstNodeFnProto *fn_proto = &proto_node->data.fn_proto; FnTypeId fn_type_id = {0}; init_fn_type_id(&fn_type_id, proto_node, proto_node->data.fn_proto.params.length); - fn_type_id.alignment = alignment; for (; fn_type_id.next_param_index < fn_type_id.param_count; fn_type_id.next_param_index += 1) { AstNode *param_node = fn_proto->params.at(fn_type_id.next_param_index); @@ -1156,6 +1174,12 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c param_info->is_noalias = param_node->data.param_decl.is_noalias; } + if (fn_proto->align_expr != nullptr) { + if (!analyze_const_align(g, child_scope, fn_proto->align_expr, &fn_type_id.alignment)) { + return g->builtin_types.entry_invalid; + } + } + fn_type_id.return_type = analyze_type_expr(g, child_scope, fn_proto->return_type); switch (fn_type_id.return_type->id) { @@ -2012,25 +2036,6 @@ TypeTableEntry *get_test_fn_type(CodeGen *g) { return g->test_fn_type; } -static bool analyze_const_align(CodeGen *g, Scope *scope, AstNode *node, uint32_t *result) { - IrInstruction *align_result = analyze_const_value(g, scope, node, get_align_amt_type(g), nullptr); - if (type_is_invalid(align_result->value.type)) - return false; - - uint32_t align_bytes = bigint_as_unsigned(&align_result->value.data.x_bigint); - if (align_bytes == 0) { - add_node_error(g, node, buf_sprintf("alignment must be >= 1")); - return false; - } - if (!is_power_of_2(align_bytes)) { - add_node_error(g, node, buf_sprintf("alignment value %" PRIu32 " is not a power of 2", align_bytes)); - return false; - } - - *result = align_bytes; - return true; -} - static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { ImportTableEntry *import = tld_fn->base.import; AstNode *source_node = tld_fn->base.source_node; @@ -2061,16 +2066,7 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { Scope *child_scope = fn_table_entry->fndef_scope ? &fn_table_entry->fndef_scope->base : tld_fn->base.parent_scope; - uint32_t alignment = 0; - if (fn_proto->align_expr != nullptr) { - if (!analyze_const_align(g, child_scope, fn_proto->align_expr, &alignment)) { - fn_table_entry->type_entry = g->builtin_types.entry_invalid; - tld_fn->base.resolution = TldResolutionInvalid; - return; - } - } - - fn_table_entry->type_entry = analyze_fn_type(g, source_node, child_scope, alignment); + fn_table_entry->type_entry = analyze_fn_type(g, source_node, child_scope); if (fn_table_entry->type_entry->id == TypeTableEntryIdInvalid) { tld_fn->base.resolution = TldResolutionInvalid; |
