parseh handles typedef void better

and introduce c_long_double type
This commit is contained in:
Andrew Kelley 2016-01-31 15:44:02 -07:00
parent c77637d172
commit 1053172854
6 changed files with 61 additions and 11 deletions

View File

@ -205,6 +205,7 @@ c_long long for ABI compatibility with C
c_ulong unsigned 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_longlong long long for ABI compatibility with C
c_ulonglong unsigned 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 ### Boolean Type

View File

@ -17,3 +17,5 @@ for each target.
Make sure that parseh sends the correct command line parameters to libclang for Make sure that parseh sends the correct command line parameters to libclang for
the given target. the given target.
Make sure that `c_long_double` codegens the correct floating point value.

View File

@ -1023,6 +1023,7 @@ struct CodeGen {
TypeTableEntry *entry_bool; TypeTableEntry *entry_bool;
TypeTableEntry *entry_int[2][4]; // [signed,unsigned][8,16,32,64] TypeTableEntry *entry_int[2][4]; // [signed,unsigned][8,16,32,64]
TypeTableEntry *entry_c_int[8]; TypeTableEntry *entry_c_int[8];
TypeTableEntry *entry_c_long_double;
TypeTableEntry *entry_u8; TypeTableEntry *entry_u8;
TypeTableEntry *entry_u16; TypeTableEntry *entry_u16;
TypeTableEntry *entry_u32; TypeTableEntry *entry_u32;

View File

@ -2918,6 +2918,18 @@ static void define_builtin_types(CodeGen *g) {
g->builtin_types.entry_f64 = entry; g->builtin_types.entry_f64 = entry;
g->primitive_type_table.put(&entry->name, 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); TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdVoid);
entry->type_ref = LLVMVoidType(); entry->type_ref = LLVMVoidType();

View File

@ -234,6 +234,19 @@ static TypeTableEntry *get_c_void_type(Context *c) {
return c->c_void_type; 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, static TypeTableEntry *resolve_type_with_table(Context *c, const Type *ty, const Decl *decl,
HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> *type_table) HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> *type_table)
{ {
@ -243,7 +256,7 @@ static TypeTableEntry *resolve_type_with_table(Context *c, const Type *ty, const
const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(ty); const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(ty);
switch (builtin_ty->getKind()) { switch (builtin_ty->getKind()) {
case BuiltinType::Void: case BuiltinType::Void:
return c->codegen->builtin_types.entry_void; return get_c_void_type(c);
case BuiltinType::Bool: case BuiltinType::Bool:
return c->codegen->builtin_types.entry_bool; return c->codegen->builtin_types.entry_bool;
case BuiltinType::Char_U: case BuiltinType::Char_U:
@ -273,6 +286,7 @@ static TypeTableEntry *resolve_type_with_table(Context *c, const Type *ty, const
case BuiltinType::Double: case BuiltinType::Double:
return c->codegen->builtin_types.entry_f64; return c->codegen->builtin_types.entry_f64;
case BuiltinType::LongDouble: case BuiltinType::LongDouble:
return c->codegen->builtin_types.entry_c_long_double;
case BuiltinType::WChar_U: case BuiltinType::WChar_U:
case BuiltinType::Char16: case BuiltinType::Char16:
case BuiltinType::Char32: 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(); 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); 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); 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 { } else {
fn_type_id.return_type = resolve_qual_type(c, fn_proto_ty->getReturnType(), decl); 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) { 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; 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<FnTypeParamInfo>(fn_type_id.param_count); 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
TypeTableEntry *param_type = resolve_qual_type(c, qt, decl); TypeTableEntry *param_type = resolve_qual_type(c, qt, decl);
if (get_underlying_type(param_type)->id == TypeTableEntryIdInvalid) { if (get_underlying_type(param_type)->id == TypeTableEntryIdInvalid) {
emit_warning(c, decl, "unresolved function proto parameter type");
return c->codegen->builtin_types.entry_invalid; 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<const ConstantArrayType *>(ty); const ConstantArrayType *const_arr_ty = static_cast<const ConstantArrayType *>(ty);
TypeTableEntry *child_type = resolve_qual_type(c, const_arr_ty->getElementType(), decl); 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(); uint64_t size = const_arr_ty->getSize().getLimitedValue();
return get_array_type(c->codegen, child_type, size); 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 // TODO
TypeTableEntry *child_type = resolve_qual_type(c, child_qt, typedef_decl); 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); TypeTableEntry *decl_type = get_typedecl_type(c->codegen, buf_ptr(type_name), child_type);
add_typedef_node(c, decl_type); add_typedef_node(c, decl_type);
} }

View File

@ -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 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 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); 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; )SOURCE", 3,
pub extern fn bar(a: u8, b: u16, c: u32, d: u64); "pub extern fn foo(a: u8, b: u8, c: i8) -> c_int;",
pub extern fn baz(a: i8, b: i16, c: i32, d: i64);)OUTPUT"); "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( add_parseh_case("noreturn attribute", R"SOURCE(
void foo(void) __attribute__((noreturn)); void foo(void) __attribute__((noreturn));
@ -1953,7 +1954,7 @@ enum Bar {
BarB, BarB,
}; };
void func(struct Foo *a, enum Bar **b); 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, x: c_int,
y: c_int, y: c_int,
} }
@ -1962,8 +1963,8 @@ export enum enum_Bar {
B, B,
} }
pub const BarA = enum_Bar.A; pub const BarA = enum_Bar.A;
pub const BarB = enum_Bar.B; pub const BarB = enum_Bar.B;)OUTPUT",
pub extern fn func(a: ?&struct_Foo, b: ?&?&enum_Bar);)OUTPUT", "pub extern fn func(a: ?&struct_Foo, b: ?&?&enum_Bar);",
R"OUTPUT(pub const Foo = struct_Foo; R"OUTPUT(pub const Foo = struct_Foo;
pub const Bar = enum_Bar;)OUTPUT"); pub const Bar = enum_Bar;)OUTPUT");
@ -2038,6 +2039,15 @@ struct Bar {
R"SOURCE(export struct struct_Foo { R"SOURCE(export struct struct_Foo {
next: ?&struct_Bar, next: ?&struct_Bar,
})SOURCE"); })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) { static void print_compiler_invocation(TestCase *test_case) {