stage1: refactor fn type analysis to use C ABI walk fn

This commit is contained in:
Andrew Kelley 2018-09-07 12:23:50 -04:00
parent be6cccb3a5
commit 04d7b565f7
No known key found for this signature in database
GPG Key ID: 4E7CD66038A4D47C
5 changed files with 64 additions and 76 deletions

View File

@ -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;
};

View File

@ -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, &param_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 = &param_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,

View File

@ -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

View File

@ -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();
}
}
}

View File

@ -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