authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-08-30 00:46:38-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-08-30 00:46:38-04:00
logfa9006f8d1aa95934f31d5bedfcd3949267c9e72
tree7551d28d4ee45e3ae5c6ebe73dd6979abe2b55ac
parentc2357830b4350a4685f867566afd79eaf2cb3c66

generic functions can access comptime args in align value

See #37

2 files changed, 36 insertions(+), 31 deletions(-)

src/analyze.cpp+27-31
...@@ -1061,13 +1061,31 @@ void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_cou...@@ -1061,13 +1061,31 @@ void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_cou
1061 fn_type_id->is_var_args = fn_proto->is_var_args;1061 fn_type_id->is_var_args = fn_proto->is_var_args;
1062}1062}
10631063
1064static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_scope, uint32_t alignment) {1064static bool analyze_const_align(CodeGen *g, Scope *scope, AstNode *node, uint32_t *result) {
1065 IrInstruction *align_result = analyze_const_value(g, scope, node, get_align_amt_type(g), nullptr);
1066 if (type_is_invalid(align_result->value.type))
1067 return false;
1068
1069 uint32_t align_bytes = bigint_as_unsigned(&align_result->value.data.x_bigint);
1070 if (align_bytes == 0) {
1071 add_node_error(g, node, buf_sprintf("alignment must be >= 1"));
1072 return false;
1073 }
1074 if (!is_power_of_2(align_bytes)) {
1075 add_node_error(g, node, buf_sprintf("alignment value %" PRIu32 " is not a power of 2", align_bytes));
1076 return false;
1077 }
1078
1079 *result = align_bytes;
1080 return true;
1081}
1082
1083static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_scope) {
1065 assert(proto_node->type == NodeTypeFnProto);1084 assert(proto_node->type == NodeTypeFnProto);
1066 AstNodeFnProto *fn_proto = &proto_node->data.fn_proto;1085 AstNodeFnProto *fn_proto = &proto_node->data.fn_proto;
10671086
1068 FnTypeId fn_type_id = {0};1087 FnTypeId fn_type_id = {0};
1069 init_fn_type_id(&fn_type_id, proto_node, proto_node->data.fn_proto.params.length);1088 init_fn_type_id(&fn_type_id, proto_node, proto_node->data.fn_proto.params.length);
1070 fn_type_id.alignment = alignment;
10711089
1072 for (; fn_type_id.next_param_index < fn_type_id.param_count; fn_type_id.next_param_index += 1) {1090 for (; fn_type_id.next_param_index < fn_type_id.param_count; fn_type_id.next_param_index += 1) {
1073 AstNode *param_node = fn_proto->params.at(fn_type_id.next_param_index);1091 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...@@ -1156,6 +1174,12 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
1156 param_info->is_noalias = param_node->data.param_decl.is_noalias;1174 param_info->is_noalias = param_node->data.param_decl.is_noalias;
1157 }1175 }
11581176
1177 if (fn_proto->align_expr != nullptr) {
1178 if (!analyze_const_align(g, child_scope, fn_proto->align_expr, &fn_type_id.alignment)) {
1179 return g->builtin_types.entry_invalid;
1180 }
1181 }
1182
1159 fn_type_id.return_type = analyze_type_expr(g, child_scope, fn_proto->return_type);1183 fn_type_id.return_type = analyze_type_expr(g, child_scope, fn_proto->return_type);
11601184
1161 switch (fn_type_id.return_type->id) {1185 switch (fn_type_id.return_type->id) {
...@@ -2012,25 +2036,6 @@ TypeTableEntry *get_test_fn_type(CodeGen *g) {...@@ -2012,25 +2036,6 @@ TypeTableEntry *get_test_fn_type(CodeGen *g) {
2012 return g->test_fn_type;2036 return g->test_fn_type;
2013}2037}
20142038
2015static bool analyze_const_align(CodeGen *g, Scope *scope, AstNode *node, uint32_t *result) {
2016 IrInstruction *align_result = analyze_const_value(g, scope, node, get_align_amt_type(g), nullptr);
2017 if (type_is_invalid(align_result->value.type))
2018 return false;
2019
2020 uint32_t align_bytes = bigint_as_unsigned(&align_result->value.data.x_bigint);
2021 if (align_bytes == 0) {
2022 add_node_error(g, node, buf_sprintf("alignment must be >= 1"));
2023 return false;
2024 }
2025 if (!is_power_of_2(align_bytes)) {
2026 add_node_error(g, node, buf_sprintf("alignment value %" PRIu32 " is not a power of 2", align_bytes));
2027 return false;
2028 }
2029
2030 *result = align_bytes;
2031 return true;
2032}
2033
2034static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {2039static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
2035 ImportTableEntry *import = tld_fn->base.import;2040 ImportTableEntry *import = tld_fn->base.import;
2036 AstNode *source_node = tld_fn->base.source_node;2041 AstNode *source_node = tld_fn->base.source_node;
...@@ -2061,16 +2066,7 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {...@@ -2061,16 +2066,7 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
20612066
2062 Scope *child_scope = fn_table_entry->fndef_scope ? &fn_table_entry->fndef_scope->base : tld_fn->base.parent_scope;2067 Scope *child_scope = fn_table_entry->fndef_scope ? &fn_table_entry->fndef_scope->base : tld_fn->base.parent_scope;
20632068
2064 uint32_t alignment = 0;2069 fn_table_entry->type_entry = analyze_fn_type(g, source_node, child_scope);
2065 if (fn_proto->align_expr != nullptr) {
2066 if (!analyze_const_align(g, child_scope, fn_proto->align_expr, &alignment)) {
2067 fn_table_entry->type_entry = g->builtin_types.entry_invalid;
2068 tld_fn->base.resolution = TldResolutionInvalid;
2069 return;
2070 }
2071 }
2072
2073 fn_table_entry->type_entry = analyze_fn_type(g, source_node, child_scope, alignment);
20742070
2075 if (fn_table_entry->type_entry->id == TypeTableEntryIdInvalid) {2071 if (fn_table_entry->type_entry->id == TypeTableEntryIdInvalid) {
2076 tld_fn->base.resolution = TldResolutionInvalid;2072 tld_fn->base.resolution = TldResolutionInvalid;
test/cases/align.zig+9
...@@ -127,3 +127,12 @@ fn fnExpects4(ptr: fn()align 4 -> i32) -> i32 {...@@ -127,3 +127,12 @@ fn fnExpects4(ptr: fn()align 4 -> i32) -> i32 {
127 ptr()127 ptr()
128}128}
129fn simple4() align 4 -> i32 { 0x19 }129fn simple4() align 4 -> i32 { 0x19 }
130
131
132test "generic function with align param" {
133 assert(whyWouldYouEverDoThis(1) == 0x1);
134 assert(whyWouldYouEverDoThis(4) == 0x1);
135 assert(whyWouldYouEverDoThis(8) == 0x1);
136}
137
138fn whyWouldYouEverDoThis(comptime align_bytes: u8) align align_bytes -> u8 { 0x1 }