From be6cccb3a51512dea011326d9ad30ad495e7c716 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 7 Sep 2018 11:52:57 -0400 Subject: stage1: c abi for big struct works --- src/codegen.hpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/codegen.hpp') diff --git a/src/codegen.hpp b/src/codegen.hpp index 6297c4611b..785ba9f05d 100644 --- a/src/codegen.hpp +++ b/src/codegen.hpp @@ -61,5 +61,6 @@ 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 -- cgit v1.2.3 From 04d7b565f78895d96e5a43e8b1f4873ea5f529cf Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 7 Sep 2018 12:23:50 -0400 Subject: stage1: refactor fn type analysis to use C ABI walk fn --- src/all_types.hpp | 7 +++++ src/analyze.cpp | 85 ++++++++----------------------------------------------- src/analyze.hpp | 3 +- src/codegen.cpp | 43 ++++++++++++++++++++++++++++ src/codegen.hpp | 2 -- 5 files changed, 64 insertions(+), 76 deletions(-) (limited to 'src/codegen.hpp') diff --git a/src/all_types.hpp b/src/all_types.hpp index a89a94c0a0..5ce8e88669 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -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 *param_di_types; + ZigList *gen_param_types; +}; + struct FnWalk { FnWalkId id; union { FnWalkAttrs attrs; FnWalkCall call; + FnWalkTypes types; } data; }; diff --git a/src/analyze.cpp b/src/analyze.cpp index a658c469ac..0fe83e0d96 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -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 *gen_param_types, - ZigList *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, diff --git a/src/analyze.hpp b/src/analyze.hpp index f13c528c5a..98e4412594 100644 --- a/src/analyze.hpp +++ b/src/analyze.hpp @@ -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 diff --git a/src/codegen.cpp b/src/codegen.cpp index 469d62f3a2..e96445ebe3 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -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(); } } } diff --git a/src/codegen.hpp b/src/codegen.hpp index 785ba9f05d..b1a4dbf6e2 100644 --- a/src/codegen.hpp +++ b/src/codegen.hpp @@ -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 -- cgit v1.2.3