mirror of
https://github.com/ziglang/zig.git
synced 2026-02-21 16:54:52 +00:00
stage1: refactor fn type analysis to use C ABI walk fn
This commit is contained in:
parent
be6cccb3a5
commit
04d7b565f7
@ -3287,6 +3287,7 @@ enum FloatMode {
|
||||
enum FnWalkId {
|
||||
FnWalkIdAttrs,
|
||||
FnWalkIdCall,
|
||||
FnWalkIdTypes,
|
||||
};
|
||||
|
||||
struct FnWalkAttrs {
|
||||
@ -3300,11 +3301,17 @@ struct FnWalkCall {
|
||||
bool is_var_args;
|
||||
};
|
||||
|
||||
struct FnWalkTypes {
|
||||
ZigList<ZigLLVMDIType *> *param_di_types;
|
||||
ZigList<LLVMTypeRef> *gen_param_types;
|
||||
};
|
||||
|
||||
struct FnWalk {
|
||||
FnWalkId id;
|
||||
union {
|
||||
FnWalkAttrs attrs;
|
||||
FnWalkCall call;
|
||||
FnWalkTypes types;
|
||||
} data;
|
||||
};
|
||||
|
||||
|
||||
@ -1061,76 +1061,6 @@ ZigType *get_ptr_to_stack_trace_type(CodeGen *g) {
|
||||
return g->ptr_to_stack_trace_type;
|
||||
}
|
||||
|
||||
bool type_is_c_abi_int(CodeGen *g, ZigType *ty) {
|
||||
size_t ty_size = type_size(g, ty);
|
||||
if (ty_size > g->pointer_size_bytes)
|
||||
return false;
|
||||
return (ty->id == ZigTypeIdInt ||
|
||||
ty->id == ZigTypeIdFloat ||
|
||||
ty->id == ZigTypeIdBool ||
|
||||
ty->id == ZigTypeIdEnum ||
|
||||
get_codegen_ptr_type(ty) != nullptr);
|
||||
}
|
||||
|
||||
// If you edit this function you have to edit the corresponding code:
|
||||
// analyze.cpp:gen_c_abi_param_type
|
||||
// codegen.cpp:gen_c_abi_param_var
|
||||
// codegen.cpp:gen_c_abi_param_var_init
|
||||
static void gen_c_abi_param_type(CodeGen *g, ZigList<LLVMTypeRef> *gen_param_types,
|
||||
ZigList<ZigLLVMDIType *> *param_di_types, ZigType *ty)
|
||||
{
|
||||
if (type_is_c_abi_int(g, ty) || ty->id == ZigTypeIdFloat ||
|
||||
ty->id == ZigTypeIdInt // TODO investigate if we need to change this
|
||||
) {
|
||||
gen_param_types->append(ty->type_ref);
|
||||
param_di_types->append(ty->di_type);
|
||||
return;
|
||||
}
|
||||
|
||||
// Arrays are just pointers
|
||||
if (ty->id == ZigTypeIdArray) {
|
||||
ZigType *gen_type = get_pointer_to_type(g, ty, true);
|
||||
gen_param_types->append(gen_type->type_ref);
|
||||
param_di_types->append(gen_type->di_type);
|
||||
return;
|
||||
}
|
||||
|
||||
if (g->zig_target.arch.arch == ZigLLVM_x86_64) {
|
||||
size_t ty_size = type_size(g, ty);
|
||||
if (ty->id == ZigTypeIdStruct || ty->id == ZigTypeIdUnion) {
|
||||
// "If the size of an object is larger than four eightbytes, or it contains unaligned
|
||||
// fields, it has class MEMORY"
|
||||
if (ty_size > 32) {
|
||||
ZigType *gen_type = get_pointer_to_type(g, ty, true);
|
||||
gen_param_types->append(gen_type->type_ref);
|
||||
param_di_types->append(gen_type->di_type);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (ty->id == ZigTypeIdStruct) {
|
||||
// "If the size of the aggregate exceeds a single eightbyte, each is classified
|
||||
// separately. Each eightbyte gets initialized to class NO_CLASS."
|
||||
if (ty_size <= 8) {
|
||||
bool contains_int = false;
|
||||
for (size_t i = 0; i < ty->data.structure.src_field_count; i += 1) {
|
||||
if (type_is_c_abi_int(g, ty->data.structure.fields[i].type_entry)) {
|
||||
contains_int = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (contains_int) {
|
||||
ZigType *gen_type = get_int_type(g, false, ty_size * 8);
|
||||
gen_param_types->append(gen_type->type_ref);
|
||||
param_di_types->append(gen_type->di_type);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// allow codegen code to report a compile error
|
||||
}
|
||||
|
||||
ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
|
||||
Error err;
|
||||
auto table_entry = g->fn_type_table.maybe_get(fn_type_id);
|
||||
@ -1249,9 +1179,10 @@ ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
|
||||
if ((err = ensure_complete_type(g, type_entry)))
|
||||
return g->builtin_types.entry_invalid;
|
||||
|
||||
if (is_c_abi) {
|
||||
gen_c_abi_param_type(g, &gen_param_types, ¶m_di_types, type_entry);
|
||||
} else if (type_has_bits(type_entry)) {
|
||||
if (is_c_abi)
|
||||
continue;
|
||||
|
||||
if (type_has_bits(type_entry)) {
|
||||
ZigType *gen_type;
|
||||
if (handle_is_ptr(type_entry)) {
|
||||
gen_type = get_pointer_to_type(g, type_entry, true);
|
||||
@ -1267,6 +1198,14 @@ ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
|
||||
}
|
||||
}
|
||||
|
||||
if (is_c_abi) {
|
||||
FnWalk fn_walk = {};
|
||||
fn_walk.id = FnWalkIdTypes;
|
||||
fn_walk.data.types.param_di_types = ¶m_di_types;
|
||||
fn_walk.data.types.gen_param_types = &gen_param_types;
|
||||
walk_function_params(g, fn_type, &fn_walk);
|
||||
}
|
||||
|
||||
fn_type->data.fn.gen_param_count = gen_param_types.length;
|
||||
|
||||
fn_type->data.fn.raw_type_ref = LLVMFunctionType(gen_return_type->type_ref,
|
||||
|
||||
@ -210,6 +210,7 @@ ZigType *get_primitive_type(CodeGen *g, Buf *name);
|
||||
bool calling_convention_allows_zig_types(CallingConvention cc);
|
||||
const char *calling_convention_name(CallingConvention cc);
|
||||
|
||||
bool type_is_c_abi_int(CodeGen *g, ZigType *ty);
|
||||
void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@ -1893,6 +1893,17 @@ static void give_up_with_c_abi_error(CodeGen *g, AstNode *source_node) {
|
||||
report_errors_and_exit(g);
|
||||
}
|
||||
|
||||
static bool type_is_c_abi_int(CodeGen *g, ZigType *ty) {
|
||||
size_t ty_size = type_size(g, ty);
|
||||
if (ty_size > g->pointer_size_bytes)
|
||||
return false;
|
||||
return (ty->id == ZigTypeIdInt ||
|
||||
ty->id == ZigTypeIdFloat ||
|
||||
ty->id == ZigTypeIdBool ||
|
||||
ty->id == ZigTypeIdEnum ||
|
||||
get_codegen_ptr_type(ty) != nullptr);
|
||||
}
|
||||
|
||||
static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk, size_t src_i) {
|
||||
// Initialized from the type for some walks, but because of C var args,
|
||||
// initialized based on callsite instructions for that one.
|
||||
@ -1919,7 +1930,14 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_
|
||||
val = ir_llvm_value(g, arg);
|
||||
break;
|
||||
}
|
||||
case FnWalkIdTypes:
|
||||
if (src_i >= fn_type->data.fn.fn_type_id.param_count)
|
||||
return false;
|
||||
param_info = &fn_type->data.fn.fn_type_id.param_info[src_i];
|
||||
ty = param_info->type;
|
||||
break;
|
||||
}
|
||||
|
||||
if (type_is_c_abi_int(g, ty) || ty->id == ZigTypeIdFloat ||
|
||||
ty->id == ZigTypeIdInt // TODO investigate if we need to change this
|
||||
) {
|
||||
@ -1943,6 +1961,10 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_
|
||||
case FnWalkIdCall:
|
||||
fn_walk->data.call.gen_param_values->append(val);
|
||||
break;
|
||||
case FnWalkIdTypes:
|
||||
fn_walk->data.types.gen_param_types->append(ty->type_ref);
|
||||
fn_walk->data.types.param_di_types->append(ty->di_type);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -1958,6 +1980,12 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_
|
||||
case FnWalkIdCall:
|
||||
fn_walk->data.call.gen_param_values->append(val);
|
||||
break;
|
||||
case FnWalkIdTypes: {
|
||||
ZigType *gen_type = get_pointer_to_type(g, ty, true);
|
||||
fn_walk->data.types.gen_param_types->append(gen_type->type_ref);
|
||||
fn_walk->data.types.param_di_types->append(gen_type->di_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -1979,6 +2007,12 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_
|
||||
case FnWalkIdCall:
|
||||
fn_walk->data.call.gen_param_values->append(val);
|
||||
break;
|
||||
case FnWalkIdTypes: {
|
||||
ZigType *gen_type = get_pointer_to_type(g, ty, true);
|
||||
fn_walk->data.types.gen_param_types->append(gen_type->type_ref);
|
||||
fn_walk->data.types.param_di_types->append(gen_type->di_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -2007,6 +2041,12 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_
|
||||
fn_walk->data.call.gen_param_values->append(loaded);
|
||||
break;
|
||||
}
|
||||
case FnWalkIdTypes: {
|
||||
ZigType *gen_type = get_int_type(g, false, ty_size * 8);
|
||||
fn_walk->data.types.gen_param_types->append(gen_type->type_ref);
|
||||
fn_walk->data.types.param_di_types->append(gen_type->di_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -2074,6 +2114,9 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) {
|
||||
case FnWalkIdCall:
|
||||
// handled before for loop
|
||||
zig_unreachable();
|
||||
case FnWalkIdTypes:
|
||||
// Not called for non-c-abi
|
||||
zig_unreachable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -61,6 +61,4 @@ void codegen_translate_c(CodeGen *g, Buf *path);
|
||||
|
||||
Buf *codegen_generate_builtin_source(CodeGen *g);
|
||||
|
||||
void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk);
|
||||
|
||||
#endif
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user