diff --git a/doc/langref.md b/doc/langref.md index 4b2c176f44..73f46a146d 100644 --- a/doc/langref.md +++ b/doc/langref.md @@ -205,6 +205,7 @@ c_long long for ABI compatibility with C c_ulong unsigned long for ABI compatibility with C c_longlong long long for ABI compatibility with C c_ulonglong unsigned long long for ABI compatibility with C +c_long_double long double for ABI compatibility with C ``` ### Boolean Type diff --git a/doc/targets.md b/doc/targets.md index fb1b32e499..de465959c9 100644 --- a/doc/targets.md +++ b/doc/targets.md @@ -17,3 +17,5 @@ for each target. Make sure that parseh sends the correct command line parameters to libclang for the given target. + +Make sure that `c_long_double` codegens the correct floating point value. diff --git a/src/all_types.hpp b/src/all_types.hpp index 1c432b42c9..f1032776db 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1023,6 +1023,7 @@ struct CodeGen { TypeTableEntry *entry_bool; TypeTableEntry *entry_int[2][4]; // [signed,unsigned][8,16,32,64] TypeTableEntry *entry_c_int[8]; + TypeTableEntry *entry_c_long_double; TypeTableEntry *entry_u8; TypeTableEntry *entry_u16; TypeTableEntry *entry_u32; diff --git a/src/codegen.cpp b/src/codegen.cpp index 88bebc56a4..36f34e5b54 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -2918,6 +2918,18 @@ static void define_builtin_types(CodeGen *g) { g->builtin_types.entry_f64 = entry; g->primitive_type_table.put(&entry->name, entry); } + { + TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdFloat); + entry->type_ref = LLVMX86FP80Type(); + buf_init_from_str(&entry->name, "c_long_double"); + entry->size_in_bits = 128; + entry->align_in_bits = 128; + entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), + 80, entry->align_in_bits, + LLVMZigEncoding_DW_ATE_float()); + g->builtin_types.entry_c_long_double = entry; + g->primitive_type_table.put(&entry->name, entry); + } { TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdVoid); entry->type_ref = LLVMVoidType(); diff --git a/src/parseh.cpp b/src/parseh.cpp index 3ac881326d..0dc853bb12 100644 --- a/src/parseh.cpp +++ b/src/parseh.cpp @@ -234,6 +234,19 @@ static TypeTableEntry *get_c_void_type(Context *c) { return c->c_void_type; } +static bool is_c_void_type(Context *c, TypeTableEntry *type_entry) { + if (!c->c_void_type) { + return false; + } + while (type_entry->id == TypeTableEntryIdTypeDecl) { + if (type_entry == c->c_void_type) { + return true; + } + type_entry = type_entry->data.type_decl.child_type; + } + return false; +} + static TypeTableEntry *resolve_type_with_table(Context *c, const Type *ty, const Decl *decl, HashMap *type_table) { @@ -243,7 +256,7 @@ static TypeTableEntry *resolve_type_with_table(Context *c, const Type *ty, const const BuiltinType *builtin_ty = static_cast(ty); switch (builtin_ty->getKind()) { case BuiltinType::Void: - return c->codegen->builtin_types.entry_void; + return get_c_void_type(c); case BuiltinType::Bool: return c->codegen->builtin_types.entry_bool; case BuiltinType::Char_U: @@ -273,6 +286,7 @@ static TypeTableEntry *resolve_type_with_table(Context *c, const Type *ty, const case BuiltinType::Double: return c->codegen->builtin_types.entry_f64; case BuiltinType::LongDouble: + return c->codegen->builtin_types.entry_c_long_double; case BuiltinType::WChar_U: case BuiltinType::Char16: case BuiltinType::Char32: @@ -322,10 +336,6 @@ static TypeTableEntry *resolve_type_with_table(Context *c, const Type *ty, const } bool is_const = child_qt.isConstQualified(); - if (child_type->id == TypeTableEntryIdVoid) { - child_type = get_c_void_type(c); - } - TypeTableEntry *non_null_pointer_type = get_pointer_to_type(c->codegen, child_type, is_const); return get_maybe_type(c->codegen, non_null_pointer_type); } @@ -421,8 +431,13 @@ static TypeTableEntry *resolve_type_with_table(Context *c, const Type *ty, const } else { fn_type_id.return_type = resolve_qual_type(c, fn_proto_ty->getReturnType(), decl); if (get_underlying_type(fn_type_id.return_type)->id == TypeTableEntryIdInvalid) { + emit_warning(c, decl, "unresolved function proto return type"); return c->codegen->builtin_types.entry_invalid; } + // convert c_void to actual void (only for return type) + if (is_c_void_type(c, fn_type_id.return_type)) { + fn_type_id.return_type = c->codegen->builtin_types.entry_void; + } } fn_type_id.param_info = allocate(fn_type_id.param_count); @@ -431,6 +446,7 @@ static TypeTableEntry *resolve_type_with_table(Context *c, const Type *ty, const TypeTableEntry *param_type = resolve_qual_type(c, qt, decl); if (get_underlying_type(param_type)->id == TypeTableEntryIdInvalid) { + emit_warning(c, decl, "unresolved function proto parameter type"); return c->codegen->builtin_types.entry_invalid; } @@ -466,6 +482,10 @@ static TypeTableEntry *resolve_type_with_table(Context *c, const Type *ty, const { const ConstantArrayType *const_arr_ty = static_cast(ty); TypeTableEntry *child_type = resolve_qual_type(c, const_arr_ty->getElementType(), decl); + if (child_type->id == TypeTableEntryIdInvalid) { + emit_warning(c, decl, "unresolved array element type"); + return child_type; + } uint64_t size = const_arr_ty->getSize().getLimitedValue(); return get_array_type(c->codegen, child_type, size); } @@ -601,6 +621,10 @@ static void visit_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl) // TODO TypeTableEntry *child_type = resolve_qual_type(c, child_qt, typedef_decl); + if (child_type->id == TypeTableEntryIdInvalid) { + emit_warning(c, typedef_decl, "typedef %s - unresolved child type", buf_ptr(type_name)); + return; + } TypeTableEntry *decl_type = get_typedecl_type(c->codegen, buf_ptr(type_name), child_type); add_typedef_node(c, decl_type); } diff --git a/test/run_tests.cpp b/test/run_tests.cpp index 3a7502b5da..3cee4852cd 100644 --- a/test/run_tests.cpp +++ b/test/run_tests.cpp @@ -1903,9 +1903,10 @@ int foo(char a, unsigned char b, signed char c); int foo(char a, unsigned char b, signed char c); // test a duplicate prototype void bar(uint8_t a, uint16_t b, uint32_t c, uint64_t d); void baz(int8_t a, int16_t b, int32_t c, int64_t d); - )SOURCE", 1, R"OUTPUT(pub extern fn foo(a: u8, b: u8, c: i8) -> c_int; -pub extern fn bar(a: u8, b: u16, c: u32, d: u64); -pub extern fn baz(a: i8, b: i16, c: i32, d: i64);)OUTPUT"); + )SOURCE", 3, + "pub extern fn foo(a: u8, b: u8, c: i8) -> c_int;", + "pub extern fn bar(a: u8, b: u16, c: u32, d: u64);", + "pub extern fn baz(a: i8, b: i16, c: i32, d: i64);"); add_parseh_case("noreturn attribute", R"SOURCE( void foo(void) __attribute__((noreturn)); @@ -1953,7 +1954,7 @@ enum Bar { BarB, }; void func(struct Foo *a, enum Bar **b); - )SOURCE", 2, R"OUTPUT(export struct struct_Foo { + )SOURCE", 3, R"OUTPUT(export struct struct_Foo { x: c_int, y: c_int, } @@ -1962,8 +1963,8 @@ export enum enum_Bar { B, } pub const BarA = enum_Bar.A; -pub const BarB = enum_Bar.B; -pub extern fn func(a: ?&struct_Foo, b: ?&?&enum_Bar);)OUTPUT", +pub const BarB = enum_Bar.B;)OUTPUT", + "pub extern fn func(a: ?&struct_Foo, b: ?&?&enum_Bar);", R"OUTPUT(pub const Foo = struct_Foo; pub const Bar = enum_Bar;)OUTPUT"); @@ -2038,6 +2039,15 @@ struct Bar { R"SOURCE(export struct struct_Foo { next: ?&struct_Bar, })SOURCE"); + + + add_parseh_case("typedef void", R"SOURCE( +typedef void Foo; +Foo fun(Foo *a); + )SOURCE", 3, + "pub type c_void = u8;", + "pub type Foo = c_void;", + "pub extern fn fun(a: ?&Foo);"); } static void print_compiler_invocation(TestCase *test_case) {