| author | |
| committer | |
| log | 04d7b565f78895d96e5a43e8b1f4873ea5f529cf |
| tree | 95ae4c50915c84dfb059784f27d84658def0c1db |
| parent | be6cccb3a51512dea011326d9ad30ad495e7c716 |
| signature |
5 files changed, 64 insertions(+), 76 deletions(-)
src/all_types.hpp+7| ... | @@ -3287,6 +3287,7 @@ enum FloatMode { | ... | @@ -3287,6 +3287,7 @@ enum FloatMode { |
| 3287 | enum FnWalkId { | 3287 | enum FnWalkId { |
| 3288 | FnWalkIdAttrs, | 3288 | FnWalkIdAttrs, |
| 3289 | FnWalkIdCall, | 3289 | FnWalkIdCall, |
| 3290 | FnWalkIdTypes, | ||
| 3290 | }; | 3291 | }; |
| 3291 | 3292 | ||
| 3292 | struct FnWalkAttrs { | 3293 | struct FnWalkAttrs { |
| ... | @@ -3300,11 +3301,17 @@ struct FnWalkCall { | ... | @@ -3300,11 +3301,17 @@ struct FnWalkCall { |
| 3300 | bool is_var_args; | 3301 | bool is_var_args; |
| 3301 | }; | 3302 | }; |
| 3302 | 3303 | ||
| 3304 | struct FnWalkTypes { | ||
| 3305 | ZigList<ZigLLVMDIType *> *param_di_types; | ||
| 3306 | ZigList<LLVMTypeRef> *gen_param_types; | ||
| 3307 | }; | ||
| 3308 | |||
| 3303 | struct FnWalk { | 3309 | struct FnWalk { |
| 3304 | FnWalkId id; | 3310 | FnWalkId id; |
| 3305 | union { | 3311 | union { |
| 3306 | FnWalkAttrs attrs; | 3312 | FnWalkAttrs attrs; |
| 3307 | FnWalkCall call; | 3313 | FnWalkCall call; |
| 3314 | FnWalkTypes types; | ||
| 3308 | } data; | 3315 | } data; |
| 3309 | }; | 3316 | }; |
| 3310 | 3317 |
src/analyze.cpp+12-73| ... | @@ -1061,76 +1061,6 @@ ZigType *get_ptr_to_stack_trace_type(CodeGen *g) { | ... | @@ -1061,76 +1061,6 @@ ZigType *get_ptr_to_stack_trace_type(CodeGen *g) { |
| 1061 | return g->ptr_to_stack_trace_type; | 1061 | return g->ptr_to_stack_trace_type; |
| 1062 | } | 1062 | } |
| 1063 | 1063 | ||
| 1064 | bool type_is_c_abi_int(CodeGen *g, ZigType *ty) { | ||
| 1065 | size_t ty_size = type_size(g, ty); | ||
| 1066 | if (ty_size > g->pointer_size_bytes) | ||
| 1067 | return false; | ||
| 1068 | return (ty->id == ZigTypeIdInt || | ||
| 1069 | ty->id == ZigTypeIdFloat || | ||
| 1070 | ty->id == ZigTypeIdBool || | ||
| 1071 | ty->id == ZigTypeIdEnum || | ||
| 1072 | get_codegen_ptr_type(ty) != nullptr); | ||
| 1073 | } | ||
| 1074 | |||
| 1075 | // If you edit this function you have to edit the corresponding code: | ||
| 1076 | // analyze.cpp:gen_c_abi_param_type | ||
| 1077 | // codegen.cpp:gen_c_abi_param_var | ||
| 1078 | // codegen.cpp:gen_c_abi_param_var_init | ||
| 1079 | static void gen_c_abi_param_type(CodeGen *g, ZigList<LLVMTypeRef> *gen_param_types, | ||
| 1080 | ZigList<ZigLLVMDIType *> *param_di_types, ZigType *ty) | ||
| 1081 | { | ||
| 1082 | if (type_is_c_abi_int(g, ty) || ty->id == ZigTypeIdFloat || | ||
| 1083 | ty->id == ZigTypeIdInt // TODO investigate if we need to change this | ||
| 1084 | ) { | ||
| 1085 | gen_param_types->append(ty->type_ref); | ||
| 1086 | param_di_types->append(ty->di_type); | ||
| 1087 | return; | ||
| 1088 | } | ||
| 1089 | |||
| 1090 | // Arrays are just pointers | ||
| 1091 | if (ty->id == ZigTypeIdArray) { | ||
| 1092 | ZigType *gen_type = get_pointer_to_type(g, ty, true); | ||
| 1093 | gen_param_types->append(gen_type->type_ref); | ||
| 1094 | param_di_types->append(gen_type->di_type); | ||
| 1095 | return; | ||
| 1096 | } | ||
| 1097 | |||
| 1098 | if (g->zig_target.arch.arch == ZigLLVM_x86_64) { | ||
| 1099 | size_t ty_size = type_size(g, ty); | ||
| 1100 | if (ty->id == ZigTypeIdStruct || ty->id == ZigTypeIdUnion) { | ||
| 1101 | // "If the size of an object is larger than four eightbytes, or it contains unaligned | ||
| 1102 | // fields, it has class MEMORY" | ||
| 1103 | if (ty_size > 32) { | ||
| 1104 | ZigType *gen_type = get_pointer_to_type(g, ty, true); | ||
| 1105 | gen_param_types->append(gen_type->type_ref); | ||
| 1106 | param_di_types->append(gen_type->di_type); | ||
| 1107 | return; | ||
| 1108 | } | ||
| 1109 | } | ||
| 1110 | if (ty->id == ZigTypeIdStruct) { | ||
| 1111 | // "If the size of the aggregate exceeds a single eightbyte, each is classified | ||
| 1112 | // separately. Each eightbyte gets initialized to class NO_CLASS." | ||
| 1113 | if (ty_size <= 8) { | ||
| 1114 | bool contains_int = false; | ||
| 1115 | for (size_t i = 0; i < ty->data.structure.src_field_count; i += 1) { | ||
| 1116 | if (type_is_c_abi_int(g, ty->data.structure.fields[i].type_entry)) { | ||
| 1117 | contains_int = true; | ||
| 1118 | break; | ||
| 1119 | } | ||
| 1120 | } | ||
| 1121 | if (contains_int) { | ||
| 1122 | ZigType *gen_type = get_int_type(g, false, ty_size * 8); | ||
| 1123 | gen_param_types->append(gen_type->type_ref); | ||
| 1124 | param_di_types->append(gen_type->di_type); | ||
| 1125 | return; | ||
| 1126 | } | ||
| 1127 | } | ||
| 1128 | } | ||
| 1129 | } | ||
| 1130 | |||
| 1131 | // allow codegen code to report a compile error | ||
| 1132 | } | ||
| 1133 | |||
| 1134 | ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) { | 1064 | ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) { |
| 1135 | Error err; | 1065 | Error err; |
| 1136 | auto table_entry = g->fn_type_table.maybe_get(fn_type_id); | 1066 | 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) { | ... | @@ -1249,9 +1179,10 @@ ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) { |
| 1249 | if ((err = ensure_complete_type(g, type_entry))) | 1179 | if ((err = ensure_complete_type(g, type_entry))) |
| 1250 | return g->builtin_types.entry_invalid; | 1180 | return g->builtin_types.entry_invalid; |
| 1251 | 1181 | ||
| 1252 | if (is_c_abi) { | 1182 | if (is_c_abi) |
| 1253 | gen_c_abi_param_type(g, &gen_param_types, &param_di_types, type_entry); | 1183 | continue; |
| 1254 | } else if (type_has_bits(type_entry)) { | 1184 | |
| 1185 | if (type_has_bits(type_entry)) { | ||
| 1255 | ZigType *gen_type; | 1186 | ZigType *gen_type; |
| 1256 | if (handle_is_ptr(type_entry)) { | 1187 | if (handle_is_ptr(type_entry)) { |
| 1257 | gen_type = get_pointer_to_type(g, type_entry, true); | 1188 | gen_type = get_pointer_to_type(g, type_entry, true); |
| ... | @@ -1267,6 +1198,14 @@ ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) { | ... | @@ -1267,6 +1198,14 @@ ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) { |
| 1267 | } | 1198 | } |
| 1268 | } | 1199 | } |
| 1269 | 1200 | ||
| 1201 | if (is_c_abi) { | ||
| 1202 | FnWalk fn_walk = {}; | ||
| 1203 | fn_walk.id = FnWalkIdTypes; | ||
| 1204 | fn_walk.data.types.param_di_types = &param_di_types; | ||
| 1205 | fn_walk.data.types.gen_param_types = &gen_param_types; | ||
| 1206 | walk_function_params(g, fn_type, &fn_walk); | ||
| 1207 | } | ||
| 1208 | |||
| 1270 | fn_type->data.fn.gen_param_count = gen_param_types.length; | 1209 | fn_type->data.fn.gen_param_count = gen_param_types.length; |
| 1271 | 1210 | ||
| 1272 | fn_type->data.fn.raw_type_ref = LLVMFunctionType(gen_return_type->type_ref, | 1211 | fn_type->data.fn.raw_type_ref = LLVMFunctionType(gen_return_type->type_ref, |
src/analyze.hpp+2-1| ... | @@ -210,6 +210,7 @@ ZigType *get_primitive_type(CodeGen *g, Buf *name); | ... | @@ -210,6 +210,7 @@ ZigType *get_primitive_type(CodeGen *g, Buf *name); |
| 210 | bool calling_convention_allows_zig_types(CallingConvention cc); | 210 | bool calling_convention_allows_zig_types(CallingConvention cc); |
| 211 | const char *calling_convention_name(CallingConvention cc); | 211 | const char *calling_convention_name(CallingConvention cc); |
| 212 | 212 | ||
| 213 | bool type_is_c_abi_int(CodeGen *g, ZigType *ty); | 213 | void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk); |
| 214 | |||
| 214 | 215 | ||
| 215 | #endif | 216 | #endif |
src/codegen.cpp+43| ... | @@ -1893,6 +1893,17 @@ static void give_up_with_c_abi_error(CodeGen *g, AstNode *source_node) { | ... | @@ -1893,6 +1893,17 @@ static void give_up_with_c_abi_error(CodeGen *g, AstNode *source_node) { |
| 1893 | report_errors_and_exit(g); | 1893 | report_errors_and_exit(g); |
| 1894 | } | 1894 | } |
| 1895 | 1895 | ||
| 1896 | static bool type_is_c_abi_int(CodeGen *g, ZigType *ty) { | ||
| 1897 | size_t ty_size = type_size(g, ty); | ||
| 1898 | if (ty_size > g->pointer_size_bytes) | ||
| 1899 | return false; | ||
| 1900 | return (ty->id == ZigTypeIdInt || | ||
| 1901 | ty->id == ZigTypeIdFloat || | ||
| 1902 | ty->id == ZigTypeIdBool || | ||
| 1903 | ty->id == ZigTypeIdEnum || | ||
| 1904 | get_codegen_ptr_type(ty) != nullptr); | ||
| 1905 | } | ||
| 1906 | |||
| 1896 | static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk, size_t src_i) { | 1907 | static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk, size_t src_i) { |
| 1897 | // Initialized from the type for some walks, but because of C var args, | 1908 | // Initialized from the type for some walks, but because of C var args, |
| 1898 | // initialized based on callsite instructions for that one. | 1909 | // 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_ | ... | @@ -1919,7 +1930,14 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ |
| 1919 | val = ir_llvm_value(g, arg); | 1930 | val = ir_llvm_value(g, arg); |
| 1920 | break; | 1931 | break; |
| 1921 | } | 1932 | } |
| 1933 | case FnWalkIdTypes: | ||
| 1934 | if (src_i >= fn_type->data.fn.fn_type_id.param_count) | ||
| 1935 | return false; | ||
| 1936 | param_info = &fn_type->data.fn.fn_type_id.param_info[src_i]; | ||
| 1937 | ty = param_info->type; | ||
| 1938 | break; | ||
| 1922 | } | 1939 | } |
| 1940 | |||
| 1923 | if (type_is_c_abi_int(g, ty) || ty->id == ZigTypeIdFloat || | 1941 | if (type_is_c_abi_int(g, ty) || ty->id == ZigTypeIdFloat || |
| 1924 | ty->id == ZigTypeIdInt // TODO investigate if we need to change this | 1942 | ty->id == ZigTypeIdInt // TODO investigate if we need to change this |
| 1925 | ) { | 1943 | ) { |
| ... | @@ -1943,6 +1961,10 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ | ... | @@ -1943,6 +1961,10 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ |
| 1943 | case FnWalkIdCall: | 1961 | case FnWalkIdCall: |
| 1944 | fn_walk->data.call.gen_param_values->append(val); | 1962 | fn_walk->data.call.gen_param_values->append(val); |
| 1945 | break; | 1963 | break; |
| 1964 | case FnWalkIdTypes: | ||
| 1965 | fn_walk->data.types.gen_param_types->append(ty->type_ref); | ||
| 1966 | fn_walk->data.types.param_di_types->append(ty->di_type); | ||
| 1967 | break; | ||
| 1946 | } | 1968 | } |
| 1947 | return true; | 1969 | return true; |
| 1948 | } | 1970 | } |
| ... | @@ -1958,6 +1980,12 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ | ... | @@ -1958,6 +1980,12 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ |
| 1958 | case FnWalkIdCall: | 1980 | case FnWalkIdCall: |
| 1959 | fn_walk->data.call.gen_param_values->append(val); | 1981 | fn_walk->data.call.gen_param_values->append(val); |
| 1960 | break; | 1982 | break; |
| 1983 | case FnWalkIdTypes: { | ||
| 1984 | ZigType *gen_type = get_pointer_to_type(g, ty, true); | ||
| 1985 | fn_walk->data.types.gen_param_types->append(gen_type->type_ref); | ||
| 1986 | fn_walk->data.types.param_di_types->append(gen_type->di_type); | ||
| 1987 | break; | ||
| 1988 | } | ||
| 1961 | } | 1989 | } |
| 1962 | return true; | 1990 | return true; |
| 1963 | } | 1991 | } |
| ... | @@ -1979,6 +2007,12 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ | ... | @@ -1979,6 +2007,12 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ |
| 1979 | case FnWalkIdCall: | 2007 | case FnWalkIdCall: |
| 1980 | fn_walk->data.call.gen_param_values->append(val); | 2008 | fn_walk->data.call.gen_param_values->append(val); |
| 1981 | break; | 2009 | break; |
| 2010 | case FnWalkIdTypes: { | ||
| 2011 | ZigType *gen_type = get_pointer_to_type(g, ty, true); | ||
| 2012 | fn_walk->data.types.gen_param_types->append(gen_type->type_ref); | ||
| 2013 | fn_walk->data.types.param_di_types->append(gen_type->di_type); | ||
| 2014 | break; | ||
| 2015 | } | ||
| 1982 | } | 2016 | } |
| 1983 | return true; | 2017 | return true; |
| 1984 | } | 2018 | } |
| ... | @@ -2007,6 +2041,12 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ | ... | @@ -2007,6 +2041,12 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ |
| 2007 | fn_walk->data.call.gen_param_values->append(loaded); | 2041 | fn_walk->data.call.gen_param_values->append(loaded); |
| 2008 | break; | 2042 | break; |
| 2009 | } | 2043 | } |
| 2044 | case FnWalkIdTypes: { | ||
| 2045 | ZigType *gen_type = get_int_type(g, false, ty_size * 8); | ||
| 2046 | fn_walk->data.types.gen_param_types->append(gen_type->type_ref); | ||
| 2047 | fn_walk->data.types.param_di_types->append(gen_type->di_type); | ||
| 2048 | break; | ||
| 2049 | } | ||
| 2010 | } | 2050 | } |
| 2011 | return true; | 2051 | return true; |
| 2012 | } | 2052 | } |
| ... | @@ -2074,6 +2114,9 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) { | ... | @@ -2074,6 +2114,9 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) { |
| 2074 | case FnWalkIdCall: | 2114 | case FnWalkIdCall: |
| 2075 | // handled before for loop | 2115 | // handled before for loop |
| 2076 | zig_unreachable(); | 2116 | zig_unreachable(); |
| 2117 | case FnWalkIdTypes: | ||
| 2118 | // Not called for non-c-abi | ||
| 2119 | zig_unreachable(); | ||
| 2077 | } | 2120 | } |
| 2078 | } | 2121 | } |
| 2079 | } | 2122 | } |
src/codegen.hpp-2| ... | @@ -61,6 +61,4 @@ void codegen_translate_c(CodeGen *g, Buf *path); | ... | @@ -61,6 +61,4 @@ void codegen_translate_c(CodeGen *g, Buf *path); |
| 61 | 61 | ||
| 62 | Buf *codegen_generate_builtin_source(CodeGen *g); | 62 | Buf *codegen_generate_builtin_source(CodeGen *g); |
| 63 | 63 | ||
| 64 | void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk); | ||
| 65 | |||
| 66 | #endif | 64 | #endif |