restore shared library functionality

This commit is contained in:
Andrew Kelley 2016-09-01 11:05:36 -07:00
parent 320e26590a
commit f18e34c2c6
4 changed files with 129 additions and 35 deletions

View File

@ -1,6 +1,3 @@
#version("2.0.0")
export library "mathtest";
export fn add(a: i32, b: i32) -> i32 {
a + b
}

View File

@ -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;

View File

@ -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) {
buf_init_from_str(out_buf, "void");
} else {
zig_panic("TODO to_c_type");
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");
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");

View File

@ -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);
}