authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-09-07 12:59:59-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-09-07 12:59:59-04:00
logc528c0090089041e63f9bdbb52f951e53ce94631
treeb533a2ddc0258ea5f362c07ac34056db12f6c160
parent04d7b565f78895d96e5a43e8b1f4873ea5f529cf
signaturelock-open Commit is signed but in an unrecognized format.

stage1: refactor param vars for C ABI


2 files changed, 76 insertions(+), 89 deletions(-)

src/all_types.hpp+10
...@@ -3288,6 +3288,7 @@ enum FnWalkId {...@@ -3288,6 +3288,7 @@ enum FnWalkId {
3288 FnWalkIdAttrs,3288 FnWalkIdAttrs,
3289 FnWalkIdCall,3289 FnWalkIdCall,
3290 FnWalkIdTypes,3290 FnWalkIdTypes,
3291 FnWalkIdVars,
3291};3292};
32923293
3293struct FnWalkAttrs {3294struct FnWalkAttrs {
...@@ -3306,12 +3307,21 @@ struct FnWalkTypes {...@@ -3306,12 +3307,21 @@ struct FnWalkTypes {
3306 ZigList<LLVMTypeRef> *gen_param_types;3307 ZigList<LLVMTypeRef> *gen_param_types;
3307};3308};
33083309
3310struct FnWalkVars {
3311 ImportTableEntry *import;
3312 LLVMValueRef llvm_fn;
3313 ZigFn *fn;
3314 ZigVar *var;
3315 unsigned gen_i;
3316};
3317
3309struct FnWalk {3318struct FnWalk {
3310 FnWalkId id;3319 FnWalkId id;
3311 union {3320 union {
3312 FnWalkAttrs attrs;3321 FnWalkAttrs attrs;
3313 FnWalkCall call;3322 FnWalkCall call;
3314 FnWalkTypes types;3323 FnWalkTypes types;
3324 FnWalkVars vars;
3315 } data;3325 } data;
3316};3326};
33173327
src/codegen.cpp+66-89
...@@ -1904,14 +1904,24 @@ static bool type_is_c_abi_int(CodeGen *g, ZigType *ty) {...@@ -1904,14 +1904,24 @@ static bool type_is_c_abi_int(CodeGen *g, ZigType *ty) {
1904 get_codegen_ptr_type(ty) != nullptr);1904 get_codegen_ptr_type(ty) != nullptr);
1905}1905}
19061906
1907static LLVMValueRef build_alloca(CodeGen *g, ZigType *type_entry, const char *name, uint32_t alignment) {
1908 assert(alignment > 0);
1909 LLVMValueRef result = LLVMBuildAlloca(g->builder, type_entry->type_ref, name);
1910 LLVMSetAlignment(result, alignment);
1911 return result;
1912}
1913
1907static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk, size_t src_i) {1914static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk, size_t src_i) {
1908 // Initialized from the type for some walks, but because of C var args,1915 // Initialized from the type for some walks, but because of C var args,
1909 // initialized based on callsite instructions for that one.1916 // initialized based on callsite instructions for that one.
1910 FnTypeParamInfo *param_info = nullptr;1917 FnTypeParamInfo *param_info = nullptr;
1911 ZigType *ty;1918 ZigType *ty;
1919 ZigType *dest_ty = nullptr;
1912 AstNode *source_node = nullptr;1920 AstNode *source_node = nullptr;
1913 LLVMValueRef val;1921 LLVMValueRef val;
1914 LLVMValueRef llvm_fn;1922 LLVMValueRef llvm_fn;
1923 unsigned di_arg_index;
1924 ZigVar *var;
1915 switch (fn_walk->id) {1925 switch (fn_walk->id) {
1916 case FnWalkIdAttrs:1926 case FnWalkIdAttrs:
1917 if (src_i >= fn_type->data.fn.fn_type_id.param_count)1927 if (src_i >= fn_type->data.fn.fn_type_id.param_count)
...@@ -1936,6 +1946,14 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_...@@ -1936,6 +1946,14 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_
1936 param_info = &fn_type->data.fn.fn_type_id.param_info[src_i];1946 param_info = &fn_type->data.fn.fn_type_id.param_info[src_i];
1937 ty = param_info->type;1947 ty = param_info->type;
1938 break;1948 break;
1949 case FnWalkIdVars:
1950 assert(src_i < fn_type->data.fn.fn_type_id.param_count);
1951 param_info = &fn_type->data.fn.fn_type_id.param_info[src_i];
1952 ty = param_info->type;
1953 var = fn_walk->data.vars.var;
1954 source_node = var->decl_node;
1955 llvm_fn = fn_walk->data.vars.llvm_fn;
1956 break;
1939 }1957 }
19401958
1941 if (type_is_c_abi_int(g, ty) || ty->id == ZigTypeIdFloat ||1959 if (type_is_c_abi_int(g, ty) || ty->id == ZigTypeIdFloat ||
...@@ -1965,6 +1983,13 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_...@@ -1965,6 +1983,13 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_
1965 fn_walk->data.types.gen_param_types->append(ty->type_ref);1983 fn_walk->data.types.gen_param_types->append(ty->type_ref);
1966 fn_walk->data.types.param_di_types->append(ty->di_type);1984 fn_walk->data.types.param_di_types->append(ty->di_type);
1967 break;1985 break;
1986 case FnWalkIdVars: {
1987 var->value_ref = build_alloca(g, ty, buf_ptr(&var->name), var->align_bytes);
1988 di_arg_index = fn_walk->data.vars.gen_i;
1989 fn_walk->data.vars.gen_i += 1;
1990 dest_ty = ty;
1991 goto var_ok;
1992 }
1968 }1993 }
1969 return true;1994 return true;
1970 }1995 }
...@@ -1986,6 +2011,13 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_...@@ -1986,6 +2011,13 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_
1986 fn_walk->data.types.param_di_types->append(gen_type->di_type);2011 fn_walk->data.types.param_di_types->append(gen_type->di_type);
1987 break;2012 break;
1988 }2013 }
2014 case FnWalkIdVars: {
2015 var->value_ref = LLVMGetParam(llvm_fn, fn_walk->data.vars.gen_i);
2016 di_arg_index = fn_walk->data.vars.gen_i;
2017 dest_ty = get_pointer_to_type(g, ty, false);
2018 fn_walk->data.vars.gen_i += 1;
2019 goto var_ok;
2020 }
1989 }2021 }
1990 return true;2022 return true;
1991 }2023 }
...@@ -2013,6 +2045,13 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_...@@ -2013,6 +2045,13 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_
2013 fn_walk->data.types.param_di_types->append(gen_type->di_type);2045 fn_walk->data.types.param_di_types->append(gen_type->di_type);
2014 break;2046 break;
2015 }2047 }
2048 case FnWalkIdVars: {
2049 di_arg_index = fn_walk->data.vars.gen_i;
2050 var->value_ref = LLVMGetParam(llvm_fn, fn_walk->data.vars.gen_i);
2051 dest_ty = get_pointer_to_type(g, ty, false);
2052 fn_walk->data.vars.gen_i += 1;
2053 goto var_ok;
2054 }
2016 }2055 }
2017 return true;2056 return true;
2018 }2057 }
...@@ -2047,6 +2086,12 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_...@@ -2047,6 +2086,12 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_
2047 fn_walk->data.types.param_di_types->append(gen_type->di_type);2086 fn_walk->data.types.param_di_types->append(gen_type->di_type);
2048 break;2087 break;
2049 }2088 }
2089 case FnWalkIdVars: {
2090 di_arg_index = fn_walk->data.vars.gen_i;
2091 var->value_ref = build_alloca(g, ty, buf_ptr(&var->name), var->align_bytes);
2092 fn_walk->data.vars.gen_i += 1;
2093 goto var_ok;
2094 }
2050 }2095 }
2051 return true;2096 return true;
2052 }2097 }
...@@ -2058,6 +2103,16 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_...@@ -2058,6 +2103,16 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_
2058 }2103 }
2059 // otherwise allow codegen code to report a compile error2104 // otherwise allow codegen code to report a compile error
2060 return false;2105 return false;
2106
2107var_ok:
2108 if (dest_ty != nullptr && var->decl_node) {
2109 // arg index + 1 because the 0 index is return value
2110 var->di_loc_var = ZigLLVMCreateParameterVariable(g->dbuilder, get_di_scope(g, var->parent_scope),
2111 buf_ptr(&var->name), fn_walk->data.vars.import->di_file,
2112 (unsigned)(var->decl_node->line + 1),
2113 dest_ty->di_type, !g->strip_debug_symbols, 0, di_arg_index + 1);
2114 }
2115 return true;
2061}2116}
20622117
2063void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) {2118void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) {
...@@ -2117,6 +2172,9 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) {...@@ -2117,6 +2172,9 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) {
2117 case FnWalkIdTypes:2172 case FnWalkIdTypes:
2118 // Not called for non-c-abi2173 // Not called for non-c-abi
2119 zig_unreachable();2174 zig_unreachable();
2175 case FnWalkIdVars:
2176 // iter_function_params_c_abi is called directly for this one
2177 zig_unreachable();
2120 }2178 }
2121 }2179 }
2122}2180}
...@@ -3344,93 +3402,7 @@ static void set_call_instr_sret(CodeGen *g, LLVMValueRef call_instr) {...@@ -3344,93 +3402,7 @@ static void set_call_instr_sret(CodeGen *g, LLVMValueRef call_instr) {
3344 LLVMAddCallSiteAttribute(call_instr, 1, sret_attr);3402 LLVMAddCallSiteAttribute(call_instr, 1, sret_attr);
3345}3403}
33463404
3347static LLVMValueRef build_alloca(CodeGen *g, ZigType *type_entry, const char *name, uint32_t alignment) {
3348 assert(alignment > 0);
3349 LLVMValueRef result = LLVMBuildAlloca(g->builder, type_entry->type_ref, name);
3350 LLVMSetAlignment(result, alignment);
3351 return result;
3352}
3353
3354// If you edit this function you have to edit the corresponding code:
3355// analyze.cpp:gen_c_abi_param_type
3356// codegen.cpp:gen_c_abi_param_var
3357// codegen.cpp:gen_c_abi_param_var_init
3358static void gen_c_abi_param_var(CodeGen *g, ImportTableEntry *import, LLVMValueRef llvm_fn, ZigFn *fn,
3359 ZigVar *var, unsigned *arg_index)
3360{
3361 ZigType *ty = var->value->type;
3362
3363 ZigType *dest_ty = nullptr;
3364 unsigned di_arg_index;
3365
3366 if (type_is_c_abi_int(g, ty) || ty->id == ZigTypeIdFloat ||
3367 ty->id == ZigTypeIdInt // TODO investigate if we need to change this
3368 ) {
3369 var->value_ref = build_alloca(g, ty, buf_ptr(&var->name), var->align_bytes);
3370 di_arg_index = *arg_index;
3371 *arg_index += 1;
3372 dest_ty = ty;
3373 goto ok;
3374 }
3375
3376 // Arrays are just pointers
3377 if (ty->id == ZigTypeIdArray) {
3378 di_arg_index = *arg_index;
3379 var->value_ref = LLVMGetParam(llvm_fn, *arg_index);
3380 dest_ty = get_pointer_to_type(g, ty, false);
3381 *arg_index += 1;
3382 goto ok;
3383 }
3384
3385 if (g->zig_target.arch.arch == ZigLLVM_x86_64) {
3386 assert(handle_is_ptr(ty));
3387 size_t ty_size = type_size(g, ty);
3388
3389 if (ty->id == ZigTypeIdStruct || ty->id == ZigTypeIdUnion) {
3390 // "If the size of an object is larger than four eightbytes, or it contains unaligned
3391 // fields, it has class MEMORY"
3392 if (ty_size > 32) {
3393 di_arg_index = *arg_index;
3394 var->value_ref = LLVMGetParam(llvm_fn, *arg_index);
3395 dest_ty = get_pointer_to_type(g, ty, false);
3396 *arg_index += 1;
3397 goto ok;
3398 }
3399 }
3400 if (ty->id == ZigTypeIdStruct) {
3401 // "If the size of the aggregate exceeds a single eightbyte, each is classified
3402 // separately. Each eightbyte gets initialized to class NO_CLASS."
3403 if (ty_size <= 8) {
3404 bool contains_int = false;
3405 for (size_t i = 0; i < ty->data.structure.src_field_count; i += 1) {
3406 if (type_is_c_abi_int(g, ty->data.structure.fields[i].type_entry)) {
3407 contains_int = true;
3408 break;
3409 }
3410 }
3411 if (contains_int) {
3412 var->value_ref = build_alloca(g, ty, buf_ptr(&var->name), var->align_bytes);
3413 *arg_index += 1;
3414 goto ok;
3415 }
3416 }
3417 }
3418 }
3419
3420 give_up_with_c_abi_error(g, fn->proto_node);
3421
3422ok:
3423 if (dest_ty != nullptr && var->decl_node) {
3424 // arg index + 1 because the 0 index is return value
3425 var->di_loc_var = ZigLLVMCreateParameterVariable(g->dbuilder, get_di_scope(g, var->parent_scope),
3426 buf_ptr(&var->name), import->di_file,
3427 (unsigned)(var->decl_node->line + 1),
3428 dest_ty->di_type, !g->strip_debug_symbols, 0, di_arg_index + 1);
3429 }
3430}
3431
3432// If you edit this function you have to edit the corresponding code:3405// If you edit this function you have to edit the corresponding code:
3433// analyze.cpp:gen_c_abi_param_type
3434// codegen.cpp:gen_c_abi_param_var3406// codegen.cpp:gen_c_abi_param_var
3435// codegen.cpp:gen_c_abi_param_var_init3407// codegen.cpp:gen_c_abi_param_var_init
3436static void gen_c_abi_param_var_init(CodeGen *g, ImportTableEntry *import, LLVMValueRef llvm_fn, ZigFn *fn,3408static void gen_c_abi_param_var_init(CodeGen *g, ImportTableEntry *import, LLVMValueRef llvm_fn, ZigFn *fn,
...@@ -6317,7 +6289,12 @@ static void do_code_gen(CodeGen *g) {...@@ -6317,7 +6289,12 @@ static void do_code_gen(CodeGen *g) {
6317 ImportTableEntry *import = get_scope_import(&fn_table_entry->fndef_scope->base);6289 ImportTableEntry *import = get_scope_import(&fn_table_entry->fndef_scope->base);
63186290
6319 // create debug variable declarations for variables and allocate all local variables6291 // create debug variable declarations for variables and allocate all local variables
6320 unsigned c_abi_arg_index = 0;6292 FnWalk fn_walk = {};
6293 fn_walk.id = FnWalkIdVars;
6294 fn_walk.data.vars.import = import;
6295 fn_walk.data.vars.fn = fn_table_entry;
6296 fn_walk.data.vars.llvm_fn = fn;
6297 fn_walk.data.vars.gen_i = 0;
6321 for (size_t var_i = 0; var_i < fn_table_entry->variable_list.length; var_i += 1) {6298 for (size_t var_i = 0; var_i < fn_table_entry->variable_list.length; var_i += 1) {
6322 ZigVar *var = fn_table_entry->variable_list.at(var_i);6299 ZigVar *var = fn_table_entry->variable_list.at(var_i);
63236300
...@@ -6337,7 +6314,8 @@ static void do_code_gen(CodeGen *g) {...@@ -6337,7 +6314,8 @@ static void do_code_gen(CodeGen *g) {
6337 var->value->type->di_type, !g->strip_debug_symbols, 0);6314 var->value->type->di_type, !g->strip_debug_symbols, 0);
63386315
6339 } else if (is_c_abi) {6316 } else if (is_c_abi) {
6340 gen_c_abi_param_var(g, import, fn, fn_table_entry, var, &c_abi_arg_index);6317 fn_walk.data.vars.var = var;
6318 iter_function_params_c_abi(g, fn_table_entry->type_entry, &fn_walk, var->src_arg_index);
6341 } else {6319 } else {
6342 assert(var->gen_arg_index != SIZE_MAX);6320 assert(var->gen_arg_index != SIZE_MAX);
6343 ZigType *gen_type;6321 ZigType *gen_type;
...@@ -6423,7 +6401,6 @@ static void do_code_gen(CodeGen *g) {...@@ -6423,7 +6401,6 @@ static void do_code_gen(CodeGen *g) {
6423 gen_var_debug_decl(g, variable);6401 gen_var_debug_decl(g, variable);
6424 }6402 }
6425 }6403 }
6426 assert(c_abi_arg_index == c_abi_arg_init_index);
64276404
6428 ir_render(g, fn_table_entry);6405 ir_render(g, fn_table_entry);
64296406