Commit 04d7b565f7
Changed files (5)
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<ZigLLVMDIType *> *param_di_types;
+ ZigList<LLVMTypeRef> *gen_param_types;
+};
+
struct FnWalk {
FnWalkId id;
union {
FnWalkAttrs attrs;
FnWalkCall call;
+ FnWalkTypes types;
} data;
};
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<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,
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
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();
}
}
}
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