mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 04:48:20 +00:00
parent
c2357830b4
commit
fa9006f8d1
@ -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;
|
||||
|
||||
@ -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 }
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user