diff options
| author | Andrew Kelley <superjoe30@gmail.com> | 2018-01-22 22:24:07 -0500 |
|---|---|---|
| committer | Andrew Kelley <superjoe30@gmail.com> | 2018-01-22 22:24:07 -0500 |
| commit | cf39819478e237255109d0343e642db70e88071b (patch) | |
| tree | 6c8232d28a484989f43075efeaa5501d5e60154b /src/codegen.cpp | |
| parent | cacba6f4357fdec8db0ea792889c60022c39fbd3 (diff) | |
| download | zig-cf39819478e237255109d0343e642db70e88071b.tar.gz zig-cf39819478e237255109d0343e642db70e88071b.zip | |
add new kind of test: generating .h files. and more
* docgen supports obj_err code kind for demonstrating
errors without explicit test cases
* add documentation for `extern enum`. See #367
* remove coldcc keyword and add @setIsCold. See #661
* add compile errors for non-extern struct, enum, unions
in function signatures
* add .h file generation for extern struct, enum, unions
Diffstat (limited to 'src/codegen.cpp')
| -rw-r--r-- | src/codegen.cpp | 186 |
1 files changed, 175 insertions, 11 deletions
diff --git a/src/codegen.cpp b/src/codegen.cpp index 15423d6315..c79da04b05 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -485,11 +485,14 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) { addLLVMFnAttr(fn_table_entry->llvm_value, "naked"); } else { LLVMSetFunctionCallConv(fn_table_entry->llvm_value, get_llvm_cc(g, fn_type->data.fn.fn_type_id.cc)); - if (fn_type->data.fn.fn_type_id.cc == CallingConventionCold) { - ZigLLVMAddFunctionAttrCold(fn_table_entry->llvm_value); - } } + bool want_cold = fn_table_entry->is_cold || fn_type->data.fn.fn_type_id.cc == CallingConventionCold; + if (want_cold) { + ZigLLVMAddFunctionAttrCold(fn_table_entry->llvm_value); + } + + LLVMSetLinkage(fn_table_entry->llvm_value, to_llvm_linkage(linkage)); if (linkage == GlobalLinkageIdInternal) { @@ -3656,6 +3659,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, case IrInstructionIdToPtrType: case IrInstructionIdPtrTypeChild: case IrInstructionIdFieldPtr: + case IrInstructionIdSetCold: case IrInstructionIdSetDebugSafety: case IrInstructionIdSetFloatMode: case IrInstructionIdArrayType: @@ -5233,6 +5237,7 @@ static void define_builtin_fns(CodeGen *g) { create_builtin_fn(g, BuiltinFnIdCompileErr, "compileError", 1); create_builtin_fn(g, BuiltinFnIdCompileLog, "compileLog", SIZE_MAX); create_builtin_fn(g, BuiltinFnIdIntType, "IntType", 2); // TODO rename to Int + create_builtin_fn(g, BuiltinFnIdSetCold, "setCold", 1); create_builtin_fn(g, BuiltinFnIdSetDebugSafety, "setDebugSafety", 2); create_builtin_fn(g, BuiltinFnIdSetFloatMode, "setFloatMode", 2); create_builtin_fn(g, BuiltinFnIdPanic, "panic", 1); @@ -5788,7 +5793,76 @@ static const char *c_int_type_names[] = { "unsigned long long", }; -static void get_c_type(CodeGen *g, TypeTableEntry *type_entry, Buf *out_buf) { +struct GenH { + ZigList<TypeTableEntry *> types_to_declare; +}; + +static void prepend_c_type_to_decl_list(CodeGen *g, GenH *gen_h, TypeTableEntry *type_entry) { + if (type_entry->gen_h_loop_flag) + return; + type_entry->gen_h_loop_flag = true; + + switch (type_entry->id) { + case TypeTableEntryIdInvalid: + case TypeTableEntryIdVar: + case TypeTableEntryIdMetaType: + case TypeTableEntryIdNumLitFloat: + case TypeTableEntryIdNumLitInt: + case TypeTableEntryIdUndefLit: + case TypeTableEntryIdNullLit: + case TypeTableEntryIdNamespace: + case TypeTableEntryIdBlock: + case TypeTableEntryIdBoundFn: + case TypeTableEntryIdArgTuple: + case TypeTableEntryIdErrorUnion: + case TypeTableEntryIdPureError: + zig_unreachable(); + case TypeTableEntryIdVoid: + case TypeTableEntryIdUnreachable: + case TypeTableEntryIdBool: + case TypeTableEntryIdInt: + case TypeTableEntryIdFloat: + return; + case TypeTableEntryIdOpaque: + gen_h->types_to_declare.append(type_entry); + return; + case TypeTableEntryIdStruct: + for (uint32_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) { + TypeStructField *field = &type_entry->data.structure.fields[i]; + prepend_c_type_to_decl_list(g, gen_h, field->type_entry); + } + gen_h->types_to_declare.append(type_entry); + return; + case TypeTableEntryIdUnion: + for (uint32_t i = 0; i < type_entry->data.unionation.src_field_count; i += 1) { + TypeUnionField *field = &type_entry->data.unionation.fields[i]; + prepend_c_type_to_decl_list(g, gen_h, field->type_entry); + } + gen_h->types_to_declare.append(type_entry); + return; + case TypeTableEntryIdEnum: + prepend_c_type_to_decl_list(g, gen_h, type_entry->data.enumeration.tag_int_type); + gen_h->types_to_declare.append(type_entry); + return; + case TypeTableEntryIdPointer: + prepend_c_type_to_decl_list(g, gen_h, type_entry->data.pointer.child_type); + return; + case TypeTableEntryIdArray: + prepend_c_type_to_decl_list(g, gen_h, type_entry->data.array.child_type); + return; + case TypeTableEntryIdMaybe: + prepend_c_type_to_decl_list(g, gen_h, type_entry->data.maybe.child_type); + return; + case TypeTableEntryIdFn: + for (size_t i = 0; i < type_entry->data.fn.fn_type_id.param_count; i += 1) { + prepend_c_type_to_decl_list(g, gen_h, type_entry->data.fn.fn_type_id.param_info[i].type); + } + prepend_c_type_to_decl_list(g, gen_h, type_entry->data.fn.fn_type_id.return_type); + return; + } +} + +static void get_c_type(CodeGen *g, GenH *gen_h, TypeTableEntry *type_entry, Buf *out_buf) { assert(type_entry); for (size_t i = 0; i < array_length(c_int_type_names); i += 1) { @@ -5816,6 +5890,8 @@ static void get_c_type(CodeGen *g, TypeTableEntry *type_entry, Buf *out_buf) { return; } + prepend_c_type_to_decl_list(g, gen_h, type_entry); + switch (type_entry->id) { case TypeTableEntryIdVoid: buf_init_from_str(out_buf, "void"); @@ -5856,7 +5932,7 @@ static void get_c_type(CodeGen *g, TypeTableEntry *type_entry, Buf *out_buf) { { Buf child_buf = BUF_INIT; TypeTableEntry *child_type = type_entry->data.pointer.child_type; - get_c_type(g, child_type, &child_buf); + get_c_type(g, gen_h, child_type, &child_buf); const char *const_str = type_entry->data.pointer.is_const ? "const " : ""; buf_resize(out_buf, 0); @@ -5872,23 +5948,37 @@ static void get_c_type(CodeGen *g, TypeTableEntry *type_entry, Buf *out_buf) { } else if (child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn) { - return get_c_type(g, child_type, out_buf); + return get_c_type(g, gen_h, child_type, out_buf); } else { zig_unreachable(); } } case TypeTableEntryIdStruct: + { + buf_init_from_str(out_buf, "struct "); + buf_append_buf(out_buf, &type_entry->name); + return; + } + case TypeTableEntryIdUnion: + { + buf_init_from_str(out_buf, "union "); + buf_append_buf(out_buf, &type_entry->name); + return; + } + case TypeTableEntryIdEnum: + { + buf_init_from_str(out_buf, "enum "); + buf_append_buf(out_buf, &type_entry->name); + return; + } case TypeTableEntryIdOpaque: { - // TODO add to table of structs we need to declare buf_init_from_buf(out_buf, &type_entry->name); return; } case TypeTableEntryIdArray: case TypeTableEntryIdErrorUnion: case TypeTableEntryIdPureError: - case TypeTableEntryIdEnum: - case TypeTableEntryIdUnion: case TypeTableEntryIdFn: zig_panic("TODO implement get_c_type for more types"); case TypeTableEntryIdInvalid: @@ -5942,6 +6032,9 @@ static void gen_h_file(CodeGen *g) { if (!g->want_h_file) return; + GenH gen_h_data = {0}; + GenH *gen_h = &gen_h_data; + codegen_add_time_event(g, "Generate .h"); assert(!g->is_test_build); @@ -5971,7 +6064,7 @@ static void gen_h_file(CodeGen *g) { FnTypeId *fn_type_id = &fn_table_entry->type_entry->data.fn.fn_type_id; Buf return_type_c = BUF_INIT; - get_c_type(g, fn_type_id->return_type, &return_type_c); + get_c_type(g, gen_h, fn_type_id->return_type, &return_type_c); buf_appendf(&h_buf, "%s %s %s(", buf_ptr(export_macro), @@ -5987,7 +6080,7 @@ static void gen_h_file(CodeGen *g) { const char *comma_str = (param_i == 0) ? "" : ", "; const char *restrict_str = param_info->is_noalias ? "restrict" : ""; - get_c_type(g, param_info->type, ¶m_type_c); + get_c_type(g, gen_h, param_info->type, ¶m_type_c); buf_appendf(&h_buf, "%s%s%s %s", comma_str, buf_ptr(¶m_type_c), restrict_str, buf_ptr(param_name)); } @@ -6027,6 +6120,77 @@ static void gen_h_file(CodeGen *g) { fprintf(out_h, "#endif\n"); fprintf(out_h, "\n"); + for (size_t type_i = 0; type_i < gen_h->types_to_declare.length; type_i += 1) { + TypeTableEntry *type_entry = gen_h->types_to_declare.at(type_i); + switch (type_entry->id) { + case TypeTableEntryIdInvalid: + case TypeTableEntryIdVar: + case TypeTableEntryIdMetaType: + case TypeTableEntryIdVoid: + case TypeTableEntryIdBool: + case TypeTableEntryIdUnreachable: + case TypeTableEntryIdInt: + case TypeTableEntryIdFloat: + case TypeTableEntryIdPointer: + case TypeTableEntryIdNumLitFloat: + case TypeTableEntryIdNumLitInt: + case TypeTableEntryIdArray: + case TypeTableEntryIdUndefLit: + case TypeTableEntryIdNullLit: + case TypeTableEntryIdErrorUnion: + case TypeTableEntryIdPureError: + case TypeTableEntryIdNamespace: + case TypeTableEntryIdBlock: + case TypeTableEntryIdBoundFn: + case TypeTableEntryIdArgTuple: + case TypeTableEntryIdMaybe: + case TypeTableEntryIdFn: + zig_unreachable(); + case TypeTableEntryIdEnum: + assert(type_entry->data.enumeration.layout == ContainerLayoutExtern); + fprintf(out_h, "enum %s {\n", buf_ptr(&type_entry->name)); + for (uint32_t field_i = 0; field_i < type_entry->data.enumeration.src_field_count; field_i += 1) { + TypeEnumField *enum_field = &type_entry->data.enumeration.fields[field_i]; + Buf *value_buf = buf_alloc(); + bigint_append_buf(value_buf, &enum_field->value, 10); + fprintf(out_h, " %s = %s", buf_ptr(enum_field->name), buf_ptr(value_buf)); + if (field_i != type_entry->data.enumeration.src_field_count - 1) { + fprintf(out_h, ","); + } + fprintf(out_h, "\n"); + } + fprintf(out_h, "};\n\n"); + break; + case TypeTableEntryIdStruct: + assert(type_entry->data.structure.layout == ContainerLayoutExtern); + fprintf(out_h, "struct %s {\n", buf_ptr(&type_entry->name)); + for (uint32_t field_i = 0; field_i < type_entry->data.structure.src_field_count; field_i += 1) { + TypeStructField *struct_field = &type_entry->data.structure.fields[field_i]; + + Buf *type_name_buf = buf_alloc(); + get_c_type(g, gen_h, struct_field->type_entry, type_name_buf); + fprintf(out_h, " %s %s;\n", buf_ptr(type_name_buf), buf_ptr(struct_field->name)); + } + fprintf(out_h, "};\n\n"); + break; + case TypeTableEntryIdUnion: + assert(type_entry->data.unionation.layout == ContainerLayoutExtern); + fprintf(out_h, "union %s {\n", buf_ptr(&type_entry->name)); + for (uint32_t field_i = 0; field_i < type_entry->data.unionation.src_field_count; field_i += 1) { + TypeUnionField *union_field = &type_entry->data.unionation.fields[field_i]; + + Buf *type_name_buf = buf_alloc(); + get_c_type(g, gen_h, union_field->type_entry, type_name_buf); + fprintf(out_h, " %s %s;\n", buf_ptr(type_name_buf), buf_ptr(union_field->name)); + } + fprintf(out_h, "};\n\n"); + break; + case TypeTableEntryIdOpaque: + fprintf(out_h, "struct %s;\n\n", buf_ptr(&type_entry->name)); + break; + } + } + fprintf(out_h, "%s", buf_ptr(&h_buf)); fprintf(out_h, "\n#endif\n"); |
