Commit f18e34c2c6

Andrew Kelley <superjoe30@gmail.com>
2016-09-01 20:05:36
restore shared library functionality
1 parent 320e265
Changed files (4)
example/shared_library/mathtest.zig
@@ -1,6 +1,3 @@
-#version("2.0.0")
-export library "mathtest";
-
 export fn add(a: i32, b: i32) -> i32 {
     a + b
 }
src/all_types.hpp
@@ -1288,7 +1288,8 @@ struct CodeGen {
     LLVMValueRef cur_ret_ptr;
     ZigList<LLVMBasicBlockRef> break_block_stack;
     ZigList<LLVMBasicBlockRef> continue_block_stack;
-    bool c_stdint_used;
+    bool c_want_stdint;
+    bool c_want_stdbool;
     AstNode *root_export_decl;
     int version_major;
     int version_minor;
src/codegen.cpp
@@ -4992,31 +4992,121 @@ void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *sou
     do_code_gen(g);
 }
 
-static void to_c_type(CodeGen *g, AstNode *type_node, Buf *out_buf) {
-    zig_panic("TODO this function needs some love");
-    TypeTableEntry *type_entry = get_resolved_expr(type_node)->type_entry;
+static const char *c_int_type_names[] = {
+    [CIntTypeShort] = "short",
+    [CIntTypeUShort] = "unsigned short",
+    [CIntTypeInt] = "int",
+    [CIntTypeUInt] = "unsigned int",
+    [CIntTypeLong] = "long",
+    [CIntTypeULong] = "unsigned long",
+    [CIntTypeLongLong] = "long long",
+    [CIntTypeULongLong] = "unsigned long long",
+};
+
+static void get_c_type(CodeGen *g, TypeTableEntry *type_entry, Buf *out_buf) {
     assert(type_entry);
 
-    if (type_entry == g->builtin_types.entry_u8) {
-        g->c_stdint_used = true;
-        buf_init_from_str(out_buf, "uint8_t");
-    } else if (type_entry == g->builtin_types.entry_i32) {
-        g->c_stdint_used = true;
-        buf_init_from_str(out_buf, "int32_t");
-    } else if (type_entry == g->builtin_types.entry_isize) {
-        g->c_stdint_used = true;
-        buf_init_from_str(out_buf, "intptr_t");
-    } else if (type_entry == g->builtin_types.entry_f32) {
-        buf_init_from_str(out_buf, "float");
-    } else if (type_entry == g->builtin_types.entry_unreachable) {
-        buf_init_from_str(out_buf, "__attribute__((__noreturn__)) void");
-    } else if (type_entry == g->builtin_types.entry_bool) {
-        buf_init_from_str(out_buf, "unsigned char");
-    } else if (type_entry == g->builtin_types.entry_void) {
+    for (int i = 0; i < array_length(c_int_type_names); i += 1) {
+        if (type_entry == g->builtin_types.entry_c_int[i]) {
+            buf_init_from_str(out_buf, c_int_type_names[i]);
+            return;
+        }
+    }
+    if (type_entry == g->builtin_types.entry_c_long_double) {
+        buf_init_from_str(out_buf, "long double");
+        return;
+    }
+    if (type_entry == g->builtin_types.entry_c_void) {
         buf_init_from_str(out_buf, "void");
-    } else {
-        zig_panic("TODO to_c_type");
+        return;
+    }
+    if (type_entry == g->builtin_types.entry_isize) {
+        g->c_want_stdint = true;
+        buf_init_from_str(out_buf, "intptr_t");
+        return;
     }
+    if (type_entry == g->builtin_types.entry_usize) {
+        g->c_want_stdint = true;
+        buf_init_from_str(out_buf, "uintptr_t");
+        return;
+    }
+
+    switch (type_entry->id) {
+        case TypeTableEntryIdVoid:
+            buf_init_from_str(out_buf, "void");
+            break;
+        case TypeTableEntryIdBool:
+            buf_init_from_str(out_buf, "bool");
+            g->c_want_stdbool = true;
+            break;
+        case TypeTableEntryIdUnreachable:
+            buf_init_from_str(out_buf, "__attribute__((__noreturn__)) void");
+            break;
+        case TypeTableEntryIdFloat:
+            switch (type_entry->data.floating.bit_count) {
+                case 32:
+                    buf_init_from_str(out_buf, "float");
+                    break;
+                case 64:
+                    buf_init_from_str(out_buf, "double");
+                    break;
+                default:
+                    zig_unreachable();
+            }
+            break;
+        case TypeTableEntryIdInt:
+            g->c_want_stdint = true;
+            buf_resize(out_buf, 0);
+            buf_appendf(out_buf, "%sint%d_t",
+                    type_entry->data.integral.is_signed ? "" : "u",
+                    type_entry->data.integral.bit_count);
+            break;
+        case TypeTableEntryIdPointer:
+            {
+                Buf child_buf = BUF_INIT;
+                TypeTableEntry *child_type = type_entry->data.pointer.child_type;
+                get_c_type(g, child_type, &child_buf);
+
+                const char *const_str = type_entry->data.pointer.is_const ? "const " : "";
+                buf_resize(out_buf, 0);
+                buf_appendf(out_buf, "%s*%s", const_str, buf_ptr(&child_buf));
+                break;
+            }
+        case TypeTableEntryIdArray:
+        case TypeTableEntryIdStruct:
+        case TypeTableEntryIdMaybe:
+        case TypeTableEntryIdErrorUnion:
+        case TypeTableEntryIdPureError:
+        case TypeTableEntryIdEnum:
+        case TypeTableEntryIdUnion:
+        case TypeTableEntryIdFn:
+        case TypeTableEntryIdTypeDecl:
+            zig_panic("TODO");
+        case TypeTableEntryIdInvalid:
+        case TypeTableEntryIdMetaType:
+        case TypeTableEntryIdGenericFn:
+        case TypeTableEntryIdNamespace:
+        case TypeTableEntryIdNumLitFloat:
+        case TypeTableEntryIdNumLitInt:
+        case TypeTableEntryIdUndefLit:
+        case TypeTableEntryIdNullLit:
+            zig_unreachable();
+    }
+}
+
+static void get_c_type_node(CodeGen *g, AstNode *type_node, Buf *out_buf) {
+    assert(type_node->type != NodeTypeSymbol || !type_node->data.symbol_expr.override_type_entry);
+
+    Expr *expr = get_resolved_expr(type_node);
+    assert(expr->type_entry);
+    assert(expr->type_entry->id == TypeTableEntryIdMetaType);
+
+    ConstExprValue *const_val = &expr->const_val;
+    assert(const_val->ok);
+
+    TypeTableEntry *type_entry = const_val->data.x_type;
+
+    return get_c_type(g, type_entry, out_buf);
 }
 
 void codegen_generate_h_file(CodeGen *g) {
@@ -5045,7 +5135,7 @@ void codegen_generate_h_file(CodeGen *g) {
             continue;
 
         Buf return_type_c = BUF_INIT;
-        to_c_type(g, fn_proto->return_type, &return_type_c);
+        get_c_type_node(g, fn_proto->return_type, &return_type_c);
 
         buf_appendf(&h_buf, "%s %s %s(",
                 buf_ptr(export_macro),
@@ -5057,7 +5147,7 @@ void codegen_generate_h_file(CodeGen *g) {
             for (int param_i = 0; param_i < fn_proto->params.length; param_i += 1) {
                 AstNode *param_decl_node = fn_proto->params.at(param_i);
                 AstNode *param_type = param_decl_node->data.param_decl.type;
-                to_c_type(g, param_type, &param_type_c);
+                get_c_type_node(g, param_type, &param_type_c);
                 buf_appendf(&h_buf, "%s %s",
                         buf_ptr(&param_type_c),
                         buf_ptr(param_decl_node->data.param_decl.name));
@@ -5080,7 +5170,9 @@ void codegen_generate_h_file(CodeGen *g) {
     fprintf(out_h, "#ifndef %s\n", buf_ptr(ifdef_dance_name));
     fprintf(out_h, "#define %s\n\n", buf_ptr(ifdef_dance_name));
 
-    if (g->c_stdint_used)
+    if (g->c_want_stdbool)
+        fprintf(out_h, "#include <stdbool.h>\n");
+    if (g->c_want_stdint)
         fprintf(out_h, "#include <stdint.h>\n");
 
     fprintf(out_h, "\n");
src/link.cpp
@@ -159,6 +159,7 @@ static void construct_linker_job_linux(LinkJob *lj) {
 
     bool is_lib = g->out_type == OutTypeLib;
     bool shared = !g->is_static && is_lib;
+    Buf *soname = nullptr;
     if (g->is_static) {
         if (g->zig_target.arch.arch == ZigLLVM_arm || g->zig_target.arch.arch == ZigLLVM_armeb ||
             g->zig_target.arch.arch == ZigLLVM_thumb || g->zig_target.arch.arch == ZigLLVM_thumbeb)
@@ -169,6 +170,11 @@ static void construct_linker_job_linux(LinkJob *lj) {
         }
     } else if (shared) {
         lj->args.append("-shared");
+
+        buf_resize(&lj->out_file, 0);
+        buf_appendf(&lj->out_file, "lib%s.so.%d.%d.%d",
+                buf_ptr(g->root_out_name), g->version_major, g->version_minor, g->version_patch);
+        soname = buf_sprintf("lib%s.so.%d", buf_ptr(g->root_out_name), g->version_major);
     }
 
     lj->args.append("-o");
@@ -211,11 +217,7 @@ static void construct_linker_job_linux(LinkJob *lj) {
         lj->args.append(buf_ptr(get_dynamic_linker(g->target_machine)));
     }
 
-    if (g->out_type == OutTypeLib) {
-        buf_resize(&lj->out_file, 0);
-        buf_appendf(&lj->out_file, "lib%s.so.%d.%d.%d",
-                buf_ptr(g->root_out_name), g->version_major, g->version_minor, g->version_patch);
-        Buf *soname = buf_sprintf("lib%s.so.%d", buf_ptr(g->root_out_name), g->version_major);
+    if (shared) {
         lj->args.append("-soname");
         lj->args.append(buf_ptr(soname));
     }
@@ -849,7 +851,9 @@ void codegen_link(CodeGen *g, const char *out_file) {
         fprintf(stderr, "%s\n", buf_ptr(&ld_stderr));
     }
 
-    if (g->out_type == OutTypeLib) {
+    if (g->out_type == OutTypeLib ||
+        g->out_type == OutTypeObj)
+    {
         codegen_generate_h_file(g);
     }