Commit 04d7b565f7

Andrew Kelley <superjoe30@gmail.com>
2018-09-07 18:23:50
stage1: refactor fn type analysis to use C ABI walk fn
1 parent be6cccb
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, &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,
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