| author | |
| committer | |
| log | 105317285402befe75289c20c4b12fccbe94aa08 |
| tree | ac322be01d56666d135e1e3c41b0b4e76eb9723b |
| parent | c77637d1720bc80f97c21214596cec9ffc617d12 |
and introduce c_long_double type6 files changed, 61 insertions(+), 11 deletions(-)
doc/langref.md+1| ... | ... | @@ -205,6 +205,7 @@ c_long long for ABI compatibility with C |
| 205 | 205 | c_ulong unsigned long for ABI compatibility with C |
| 206 | 206 | c_longlong long long for ABI compatibility with C |
| 207 | 207 | c_ulonglong unsigned long long for ABI compatibility with C |
| 208 | c_long_double long double for ABI compatibility with C | |
| 208 | 209 | ``` |
| 209 | 210 | |
| 210 | 211 | ### Boolean Type |
doc/targets.md+2| ... | ... | @@ -17,3 +17,5 @@ for each target. |
| 17 | 17 | |
| 18 | 18 | Make sure that parseh sends the correct command line parameters to libclang for |
| 19 | 19 | the given target. |
| 20 | ||
| 21 | Make sure that `c_long_double` codegens the correct floating point value. |
src/all_types.hpp+1| ... | ... | @@ -1023,6 +1023,7 @@ struct CodeGen { |
| 1023 | 1023 | TypeTableEntry *entry_bool; |
| 1024 | 1024 | TypeTableEntry *entry_int[2][4]; // [signed,unsigned][8,16,32,64] |
| 1025 | 1025 | TypeTableEntry *entry_c_int[8]; |
| 1026 | TypeTableEntry *entry_c_long_double; | |
| 1026 | 1027 | TypeTableEntry *entry_u8; |
| 1027 | 1028 | TypeTableEntry *entry_u16; |
| 1028 | 1029 | TypeTableEntry *entry_u32; |
src/codegen.cpp+12| ... | ... | @@ -2918,6 +2918,18 @@ static void define_builtin_types(CodeGen *g) { |
| 2918 | 2918 | g->builtin_types.entry_f64 = entry; |
| 2919 | 2919 | g->primitive_type_table.put(&entry->name, entry); |
| 2920 | 2920 | } |
| 2921 | { | |
| 2922 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdFloat); | |
| 2923 | entry->type_ref = LLVMX86FP80Type(); | |
| 2924 | buf_init_from_str(&entry->name, "c_long_double"); | |
| 2925 | entry->size_in_bits = 128; | |
| 2926 | entry->align_in_bits = 128; | |
| 2927 | entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), | |
| 2928 | 80, entry->align_in_bits, | |
| 2929 | LLVMZigEncoding_DW_ATE_float()); | |
| 2930 | g->builtin_types.entry_c_long_double = entry; | |
| 2931 | g->primitive_type_table.put(&entry->name, entry); | |
| 2932 | } | |
| 2921 | 2933 | { |
| 2922 | 2934 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdVoid); |
| 2923 | 2935 | entry->type_ref = LLVMVoidType(); |
src/parseh.cpp+29-5| ... | ... | @@ -234,6 +234,19 @@ static TypeTableEntry *get_c_void_type(Context *c) { |
| 234 | 234 | return c->c_void_type; |
| 235 | 235 | } |
| 236 | 236 | |
| 237 | static bool is_c_void_type(Context *c, TypeTableEntry *type_entry) { | |
| 238 | if (!c->c_void_type) { | |
| 239 | return false; | |
| 240 | } | |
| 241 | while (type_entry->id == TypeTableEntryIdTypeDecl) { | |
| 242 | if (type_entry == c->c_void_type) { | |
| 243 | return true; | |
| 244 | } | |
| 245 | type_entry = type_entry->data.type_decl.child_type; | |
| 246 | } | |
| 247 | return false; | |
| 248 | } | |
| 249 | ||
| 237 | 250 | static TypeTableEntry *resolve_type_with_table(Context *c, const Type *ty, const Decl *decl, |
| 238 | 251 | HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> *type_table) |
| 239 | 252 | { |
| ... | ... | @@ -243,7 +256,7 @@ static TypeTableEntry *resolve_type_with_table(Context *c, const Type *ty, const |
| 243 | 256 | const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(ty); |
| 244 | 257 | switch (builtin_ty->getKind()) { |
| 245 | 258 | case BuiltinType::Void: |
| 246 | return c->codegen->builtin_types.entry_void; | |
| 259 | return get_c_void_type(c); | |
| 247 | 260 | case BuiltinType::Bool: |
| 248 | 261 | return c->codegen->builtin_types.entry_bool; |
| 249 | 262 | case BuiltinType::Char_U: |
| ... | ... | @@ -273,6 +286,7 @@ static TypeTableEntry *resolve_type_with_table(Context *c, const Type *ty, const |
| 273 | 286 | case BuiltinType::Double: |
| 274 | 287 | return c->codegen->builtin_types.entry_f64; |
| 275 | 288 | case BuiltinType::LongDouble: |
| 289 | return c->codegen->builtin_types.entry_c_long_double; | |
| 276 | 290 | case BuiltinType::WChar_U: |
| 277 | 291 | case BuiltinType::Char16: |
| 278 | 292 | case BuiltinType::Char32: |
| ... | ... | @@ -322,10 +336,6 @@ static TypeTableEntry *resolve_type_with_table(Context *c, const Type *ty, const |
| 322 | 336 | } |
| 323 | 337 | bool is_const = child_qt.isConstQualified(); |
| 324 | 338 | |
| 325 | if (child_type->id == TypeTableEntryIdVoid) { | |
| 326 | child_type = get_c_void_type(c); | |
| 327 | } | |
| 328 | ||
| 329 | 339 | TypeTableEntry *non_null_pointer_type = get_pointer_to_type(c->codegen, child_type, is_const); |
| 330 | 340 | return get_maybe_type(c->codegen, non_null_pointer_type); |
| 331 | 341 | } |
| ... | ... | @@ -421,8 +431,13 @@ static TypeTableEntry *resolve_type_with_table(Context *c, const Type *ty, const |
| 421 | 431 | } else { |
| 422 | 432 | fn_type_id.return_type = resolve_qual_type(c, fn_proto_ty->getReturnType(), decl); |
| 423 | 433 | if (get_underlying_type(fn_type_id.return_type)->id == TypeTableEntryIdInvalid) { |
| 434 | emit_warning(c, decl, "unresolved function proto return type"); | |
| 424 | 435 | return c->codegen->builtin_types.entry_invalid; |
| 425 | 436 | } |
| 437 | // convert c_void to actual void (only for return type) | |
| 438 | if (is_c_void_type(c, fn_type_id.return_type)) { | |
| 439 | fn_type_id.return_type = c->codegen->builtin_types.entry_void; | |
| 440 | } | |
| 426 | 441 | } |
| 427 | 442 | |
| 428 | 443 | fn_type_id.param_info = allocate<FnTypeParamInfo>(fn_type_id.param_count); |
| ... | ... | @@ -431,6 +446,7 @@ static TypeTableEntry *resolve_type_with_table(Context *c, const Type *ty, const |
| 431 | 446 | TypeTableEntry *param_type = resolve_qual_type(c, qt, decl); |
| 432 | 447 | |
| 433 | 448 | if (get_underlying_type(param_type)->id == TypeTableEntryIdInvalid) { |
| 449 | emit_warning(c, decl, "unresolved function proto parameter type"); | |
| 434 | 450 | return c->codegen->builtin_types.entry_invalid; |
| 435 | 451 | } |
| 436 | 452 | |
| ... | ... | @@ -466,6 +482,10 @@ static TypeTableEntry *resolve_type_with_table(Context *c, const Type *ty, const |
| 466 | 482 | { |
| 467 | 483 | const ConstantArrayType *const_arr_ty = static_cast<const ConstantArrayType *>(ty); |
| 468 | 484 | TypeTableEntry *child_type = resolve_qual_type(c, const_arr_ty->getElementType(), decl); |
| 485 | if (child_type->id == TypeTableEntryIdInvalid) { | |
| 486 | emit_warning(c, decl, "unresolved array element type"); | |
| 487 | return child_type; | |
| 488 | } | |
| 469 | 489 | uint64_t size = const_arr_ty->getSize().getLimitedValue(); |
| 470 | 490 | return get_array_type(c->codegen, child_type, size); |
| 471 | 491 | } |
| ... | ... | @@ -601,6 +621,10 @@ static void visit_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl) |
| 601 | 621 | // TODO |
| 602 | 622 | |
| 603 | 623 | TypeTableEntry *child_type = resolve_qual_type(c, child_qt, typedef_decl); |
| 624 | if (child_type->id == TypeTableEntryIdInvalid) { | |
| 625 | emit_warning(c, typedef_decl, "typedef %s - unresolved child type", buf_ptr(type_name)); | |
| 626 | return; | |
| 627 | } | |
| 604 | 628 | TypeTableEntry *decl_type = get_typedecl_type(c->codegen, buf_ptr(type_name), child_type); |
| 605 | 629 | add_typedef_node(c, decl_type); |
| 606 | 630 | } |
test/run_tests.cpp+16-6| ... | ... | @@ -1903,9 +1903,10 @@ int foo(char a, unsigned char b, signed char c); |
| 1903 | 1903 | int foo(char a, unsigned char b, signed char c); // test a duplicate prototype |
| 1904 | 1904 | void bar(uint8_t a, uint16_t b, uint32_t c, uint64_t d); |
| 1905 | 1905 | void baz(int8_t a, int16_t b, int32_t c, int64_t d); |
| 1906 | )SOURCE", 1, R"OUTPUT(pub extern fn foo(a: u8, b: u8, c: i8) -> c_int; | |
| 1907 | pub extern fn bar(a: u8, b: u16, c: u32, d: u64); | |
| 1908 | pub extern fn baz(a: i8, b: i16, c: i32, d: i64);)OUTPUT"); | |
| 1906 | )SOURCE", 3, | |
| 1907 | "pub extern fn foo(a: u8, b: u8, c: i8) -> c_int;", | |
| 1908 | "pub extern fn bar(a: u8, b: u16, c: u32, d: u64);", | |
| 1909 | "pub extern fn baz(a: i8, b: i16, c: i32, d: i64);"); | |
| 1909 | 1910 | |
| 1910 | 1911 | add_parseh_case("noreturn attribute", R"SOURCE( |
| 1911 | 1912 | void foo(void) __attribute__((noreturn)); |
| ... | ... | @@ -1953,7 +1954,7 @@ enum Bar { |
| 1953 | 1954 | BarB, |
| 1954 | 1955 | }; |
| 1955 | 1956 | void func(struct Foo *a, enum Bar **b); |
| 1956 | )SOURCE", 2, R"OUTPUT(export struct struct_Foo { | |
| 1957 | )SOURCE", 3, R"OUTPUT(export struct struct_Foo { | |
| 1957 | 1958 | x: c_int, |
| 1958 | 1959 | y: c_int, |
| 1959 | 1960 | } |
| ... | ... | @@ -1962,8 +1963,8 @@ export enum enum_Bar { |
| 1962 | 1963 | B, |
| 1963 | 1964 | } |
| 1964 | 1965 | pub const BarA = enum_Bar.A; |
| 1965 | pub const BarB = enum_Bar.B; | |
| 1966 | pub extern fn func(a: ?&struct_Foo, b: ?&?&enum_Bar);)OUTPUT", | |
| 1966 | pub const BarB = enum_Bar.B;)OUTPUT", | |
| 1967 | "pub extern fn func(a: ?&struct_Foo, b: ?&?&enum_Bar);", | |
| 1967 | 1968 | R"OUTPUT(pub const Foo = struct_Foo; |
| 1968 | 1969 | pub const Bar = enum_Bar;)OUTPUT"); |
| 1969 | 1970 | |
| ... | ... | @@ -2038,6 +2039,15 @@ struct Bar { |
| 2038 | 2039 | R"SOURCE(export struct struct_Foo { |
| 2039 | 2040 | next: ?&struct_Bar, |
| 2040 | 2041 | })SOURCE"); |
| 2042 | ||
| 2043 | ||
| 2044 | add_parseh_case("typedef void", R"SOURCE( | |
| 2045 | typedef void Foo; | |
| 2046 | Foo fun(Foo *a); | |
| 2047 | )SOURCE", 3, | |
| 2048 | "pub type c_void = u8;", | |
| 2049 | "pub type Foo = c_void;", | |
| 2050 | "pub extern fn fun(a: ?&Foo);"); | |
| 2041 | 2051 | } |
| 2042 | 2052 | |
| 2043 | 2053 | static void print_compiler_invocation(TestCase *test_case) { |