Commit fa9006f8d1
Changed files (2)
src
test
cases
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;
test/cases/align.zig
@@ -127,3 +127,12 @@ fn fnExpects4(ptr: fn()align 4 -> i32) -> i32 {
ptr()
}
fn simple4() align 4 -> i32 { 0x19 }
+
+
+test "generic function with align param" {
+ assert(whyWouldYouEverDoThis(1) == 0x1);
+ assert(whyWouldYouEverDoThis(4) == 0x1);
+ assert(whyWouldYouEverDoThis(8) == 0x1);
+}
+
+fn whyWouldYouEverDoThis(comptime align_bytes: u8) align align_bytes -> u8 { 0x1 }