diff options
| author | Veikka Tuominen <git@vexu.eu> | 2021-02-08 11:07:44 +0200 |
|---|---|---|
| committer | Veikka Tuominen <git@vexu.eu> | 2021-02-16 16:40:02 +0200 |
| commit | bb867b071a9e2fa69f39a45532dffa0f51ffdbfd (patch) | |
| tree | 493ab077cfcf1501a2fa17692b83178f74eb6489 | |
| parent | f36849fed24b54476ecadacb52d9a1b55ae14274 (diff) | |
| download | zig-bb867b071a9e2fa69f39a45532dffa0f51ffdbfd.tar.gz zig-bb867b071a9e2fa69f39a45532dffa0f51ffdbfd.zip | |
translate-c: convert vardecl and typedef
| -rw-r--r-- | src/astgen.zig | 70 | ||||
| -rw-r--r-- | src/translate_c.zig | 429 | ||||
| -rw-r--r-- | src/translate_c/ast.zig | 42 |
3 files changed, 233 insertions, 308 deletions
diff --git a/src/astgen.zig b/src/astgen.zig index 56d1497f63..dd600e2840 100644 --- a/src/astgen.zig +++ b/src/astgen.zig @@ -2664,8 +2664,11 @@ fn identifier( return mod.failNode(scope, ident, "TODO implement '_' identifier", .{}); } - if (getSimplePrimitiveValue(ident_name)) |typed_value| { - const result = try addZIRInstConst(mod, scope, src, typed_value); + if (simple_types.get(ident_name)) |val_tag| { + const result = try addZIRInstConst(mod, scope, src, TypedValue{ + .ty = Type.initTag(.type), + .val = Value.initTag(val_tag), + }); return rvalue(mod, scope, rl, result); } @@ -3325,42 +3328,33 @@ fn callExpr( return rvalue(mod, scope, rl, result); } -fn getSimplePrimitiveValue(name: []const u8) ?TypedValue { - const simple_types = std.ComptimeStringMap(Value.Tag, .{ - .{ "u8", .u8_type }, - .{ "i8", .i8_type }, - .{ "isize", .isize_type }, - .{ "usize", .usize_type }, - .{ "c_short", .c_short_type }, - .{ "c_ushort", .c_ushort_type }, - .{ "c_int", .c_int_type }, - .{ "c_uint", .c_uint_type }, - .{ "c_long", .c_long_type }, - .{ "c_ulong", .c_ulong_type }, - .{ "c_longlong", .c_longlong_type }, - .{ "c_ulonglong", .c_ulonglong_type }, - .{ "c_longdouble", .c_longdouble_type }, - .{ "f16", .f16_type }, - .{ "f32", .f32_type }, - .{ "f64", .f64_type }, - .{ "f128", .f128_type }, - .{ "c_void", .c_void_type }, - .{ "bool", .bool_type }, - .{ "void", .void_type }, - .{ "type", .type_type }, - .{ "anyerror", .anyerror_type }, - .{ "comptime_int", .comptime_int_type }, - .{ "comptime_float", .comptime_float_type }, - .{ "noreturn", .noreturn_type }, - }); - if (simple_types.get(name)) |tag| { - return TypedValue{ - .ty = Type.initTag(.type), - .val = Value.initTag(tag), - }; - } - return null; -} +pub const simple_types = std.ComptimeStringMap(Value.Tag, .{ + .{ "u8", .u8_type }, + .{ "i8", .i8_type }, + .{ "isize", .isize_type }, + .{ "usize", .usize_type }, + .{ "c_short", .c_short_type }, + .{ "c_ushort", .c_ushort_type }, + .{ "c_int", .c_int_type }, + .{ "c_uint", .c_uint_type }, + .{ "c_long", .c_long_type }, + .{ "c_ulong", .c_ulong_type }, + .{ "c_longlong", .c_longlong_type }, + .{ "c_ulonglong", .c_ulonglong_type }, + .{ "c_longdouble", .c_longdouble_type }, + .{ "f16", .f16_type }, + .{ "f32", .f32_type }, + .{ "f64", .f64_type }, + .{ "f128", .f128_type }, + .{ "c_void", .c_void_type }, + .{ "bool", .bool_type }, + .{ "void", .void_type }, + .{ "type", .type_type }, + .{ "anyerror", .anyerror_type }, + .{ "comptime_int", .comptime_int_type }, + .{ "comptime_float", .comptime_float_type }, + .{ "noreturn", .noreturn_type }, +}); fn nodeMayNeedMemoryLocation(start_node: *ast.Node, scope: *Scope) bool { var node = start_node; diff --git a/src/translate_c.zig b/src/translate_c.zig index 2bbfe0a562..bcefc41971 100644 --- a/src/translate_c.zig +++ b/src/translate_c.zig @@ -614,25 +614,21 @@ fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void { return addTopLevelDecl(c, fn_name, &proto_node.base); } -fn transQualTypeMaybeInitialized(rp: RestorePoint, qt: clang.QualType, decl_init: ?*const clang.Expr, loc: clang.SourceLocation) TransError!*ast.Node { +fn transQualTypeMaybeInitialized(c: *Context, qt: clang.QualType, decl_init: ?*const clang.Expr, loc: clang.SourceLocation) TransError!Node { return if (decl_init) |init_expr| - transQualTypeInitialized(rp, qt, init_expr, loc) + transQualTypeInitialized(c, qt, init_expr, loc) else - transQualType(rp, qt, loc); + transQualType(c, qt, loc); } + /// if mangled_name is not null, this var decl was declared in a block scope. fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]const u8) Error!void { const var_name = mangled_name orelse try c.str(@ptrCast(*const clang.NamedDecl, var_decl).getName_bytes_begin()); if (c.global_scope.sym_table.contains(var_name)) return; // Avoid processing this decl twice - const rp = makeRestorePoint(c); - const visib_tok = if (mangled_name) |_| null else try appendToken(c, .Keyword_pub, "pub"); - - const thread_local_token = if (var_decl.getTLSKind() == .None) - null - else - try appendToken(c, .Keyword_threadlocal, "threadlocal"); + const is_pub = mangled_name == null; + const is_thread_local = var_decl.getTLSKind() != .None; const scope = &c.global_scope.base; // TODO https://github.com/ziglang/zig/issues/3756 @@ -651,42 +647,27 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co // does the same as: // extern int foo; // int foo = 2; - const extern_tok = if (storage_class == .Extern and !has_init) - try appendToken(c, .Keyword_extern, "extern") - else if (storage_class != .Static) - try appendToken(c, .Keyword_export, "export") - else - null; - - const mut_tok = if (is_const) - try appendToken(c, .Keyword_const, "const") - else - try appendToken(c, .Keyword_var, "var"); + const is_extern = storage_class == .Extern and !has_init; + const is_export = !is_extern and storage_class != .Static; - const name_tok = try appendIdentifier(c, checked_name); - - _ = try appendToken(c, .Colon, ":"); - - const type_node = transQualTypeMaybeInitialized(rp, qual_type, decl_init, var_decl_loc) catch |err| switch (err) { + const type_node = transQualTypeMaybeInitialized(c, qual_type, decl_init, var_decl_loc) catch |err| switch (err) { error.UnsupportedTranslation, error.UnsupportedType => { return failDecl(c, var_decl_loc, checked_name, "unable to resolve variable type", .{}); }, error.OutOfMemory => |e| return e, }; - var eq_tok: ast.TokenIndex = undefined; - var init_node: ?*ast.Node = null; + var init_node: ?Node = null; // If the initialization expression is not present, initialize with undefined. // If it is an integer literal, we can skip the @as since it will be redundant // with the variable type. if (has_init) { - eq_tok = try appendToken(c, .Equal, "="); if (decl_init) |expr| { const node_or_error = if (expr.getStmtClass() == .StringLiteralClass) - transStringLiteralAsArray(rp, &c.global_scope.base, @ptrCast(*const clang.StringLiteral, expr), zigArraySize(rp.c, type_node) catch 0) + transStringLiteralAsArray(c, scope, @ptrCast(*const clang.StringLiteral, expr), zigArraySize(c, type_node) catch 0) else - transExprCoercing(rp, scope, expr, .used, .r_value); + transExprCoercing(c, scope, expr, .used, .r_value); init_node = node_or_error catch |err| switch (err) { error.UnsupportedTranslation, error.UnsupportedType, @@ -695,118 +676,83 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co }, error.OutOfMemory => |e| return e, }; + if (!qualTypeIsBoolean(qual_type) and isBoolRes(init_node)) { + init_node = try Node.bool_to_int.create(c.arena, init_node); + } } else { - init_node = try transCreateNodeUndefinedLiteral(c); + init_node = Node.undefined_literal.init(); } } else if (storage_class != .Extern) { - eq_tok = try appendToken(c, .Equal, "="); // The C language specification states that variables with static or threadlocal // storage without an initializer are initialized to a zero value. // @import("std").mem.zeroes(T) - const import_fn_call = try c.createBuiltinCall("@import", 1); - const std_node = try transCreateNodeStringLiteral(c, "\"std\""); - import_fn_call.params()[0] = std_node; - import_fn_call.rparen_token = try appendToken(c, .RParen, ")"); - const inner_field_access = try transCreateNodeFieldAccess(c, &import_fn_call.base, "mem"); - const outer_field_access = try transCreateNodeFieldAccess(c, inner_field_access, "zeroes"); - - const zero_init_call = try c.createCall(outer_field_access, 1); - zero_init_call.params()[0] = type_node; - zero_init_call.rtoken = try appendToken(c, .RParen, ")"); - - init_node = &zero_init_call.base; + init_node = try Node.std_mem_zeroes.create(c.arena, type_node); } - const linksection_expr = blk: { + const linksection_string = blk: { var str_len: usize = undefined; if (var_decl.getSectionAttribute(&str_len)) |str_ptr| { - _ = try appendToken(rp.c, .Keyword_linksection, "linksection"); - _ = try appendToken(rp.c, .LParen, "("); - const expr = try transCreateNodeStringLiteral( - rp.c, - try std.fmt.allocPrint(rp.c.arena, "\"{s}\"", .{str_ptr[0..str_len]}), - ); - _ = try appendToken(rp.c, .RParen, ")"); - - break :blk expr; + break :blk str_ptr[0..str_len]; } break :blk null; }; - const align_expr = blk: { - const alignment = var_decl.getAlignedAttribute(rp.c.clang_context); + const alignment = blk: { + const alignment = var_decl.getAlignedAttribute(c.clang_context); if (alignment != 0) { - _ = try appendToken(rp.c, .Keyword_align, "align"); - _ = try appendToken(rp.c, .LParen, "("); // Clang reports the alignment in bits - const expr = try transCreateNodeInt(rp.c, alignment / 8); - _ = try appendToken(rp.c, .RParen, ")"); - - break :blk expr; + break :blk alignment / 8; } break :blk null; }; - const node = try ast.Node.VarDecl.create(c.arena, .{ - .name_token = name_tok, - .mut_token = mut_tok, - .semicolon_token = try appendToken(c, .Semicolon, ";"), - }, .{ - .visib_token = visib_tok, - .thread_local_token = thread_local_token, - .eq_token = eq_tok, - .extern_export_token = extern_tok, - .type_node = type_node, - .align_node = align_expr, - .section_node = linksection_expr, - .init_node = init_node, + const node = try Node.var_decl.create(c.arena, .{ + .is_pub = is_pub, + .is_const = is_const, + .is_extern = is_extern, + .is_export = is_export, + .linksection_string = linksection_string, + .alignment = alignment, + .name = checked_name, + .type = type_node, + .init = init_node, }); return addTopLevelDecl(c, checked_name, &node.base); } -fn transTypeDefAsBuiltin(c: *Context, typedef_decl: *const clang.TypedefNameDecl, builtin_name: []const u8) !*ast.Node { +fn transTypeDefAsBuiltin(c: *Context, typedef_decl: *const clang.TypedefNameDecl, builtin_name: []const u8) !Node { _ = try c.decl_table.put(c.gpa, @ptrToInt(typedef_decl.getCanonicalDecl()), builtin_name); - return transCreateNodeIdentifier(c, builtin_name); -} - -fn checkForBuiltinTypedef(checked_name: []const u8) ?[]const u8 { - const table = [_][2][]const u8{ - .{ "uint8_t", "u8" }, - .{ "int8_t", "i8" }, - .{ "uint16_t", "u16" }, - .{ "int16_t", "i16" }, - .{ "uint32_t", "u32" }, - .{ "int32_t", "i32" }, - .{ "uint64_t", "u64" }, - .{ "int64_t", "i64" }, - .{ "intptr_t", "isize" }, - .{ "uintptr_t", "usize" }, - .{ "ssize_t", "isize" }, - .{ "size_t", "usize" }, - }; - - for (table) |entry| { - if (mem.eql(u8, checked_name, entry[0])) { - return entry[1]; - } - } - - return null; -} + return Node.identifier.create(c.arena, builtin_name); +} + +const builtin_typedef_map = std.ComptimeStringMap([]const u8, .{ + .{ "uint8_t", "u8" }, + .{ "int8_t", "i8" }, + .{ "uint16_t", "u16" }, + .{ "int16_t", "i16" }, + .{ "uint32_t", "u32" }, + .{ "int32_t", "i32" }, + .{ "uint64_t", "u64" }, + .{ "int64_t", "i64" }, + .{ "intptr_t", "isize" }, + .{ "uintptr_t", "usize" }, + .{ "ssize_t", "isize" }, + .{ "size_t", "usize" }, +}); -fn transTypeDef(c: *Context, typedef_decl: *const clang.TypedefNameDecl, top_level_visit: bool) Error!?*ast.Node { +fn transTypeDef(c: *Context, typedef_decl: *const clang.TypedefNameDecl, top_level_visit: bool) Error!?Node { if (c.decl_table.get(@ptrToInt(typedef_decl.getCanonicalDecl()))) |name| return transCreateNodeIdentifier(c, name); // Avoid processing this decl twice - const rp = makeRestorePoint(c); const typedef_name = try c.str(@ptrCast(*const clang.NamedDecl, typedef_decl).getName_bytes_begin()); // TODO https://github.com/ziglang/zig/issues/3756 // TODO https://github.com/ziglang/zig/issues/1802 const checked_name = if (isZigPrimitiveType(typedef_name)) try std.fmt.allocPrint(c.arena, "{s}_{d}", .{ typedef_name, c.getMangle() }) else typedef_name; - if (checkForBuiltinTypedef(checked_name)) |builtin| { - return transTypeDefAsBuiltin(c, typedef_decl, builtin); + if (builtin_typedef_map.get(checked_name)) |builtin| { + _ = try c.decl_table.put(c.gpa, @ptrToInt(typedef_decl.getCanonicalDecl()), builtin); + return Node.identifier.create(c.arena, builtin); } if (!top_level_visit) { @@ -814,42 +760,36 @@ fn transTypeDef(c: *Context, typedef_decl: *const clang.TypedefNameDecl, top_lev } _ = try c.decl_table.put(c.gpa, @ptrToInt(typedef_decl.getCanonicalDecl()), checked_name); - const node = (try transCreateNodeTypedef(rp, typedef_decl, true, checked_name)) orelse return null; + const node = (try transCreateNodeTypedef(c, typedef_decl, true, checked_name)) orelse return null; try addTopLevelDecl(c, checked_name, node); return transCreateNodeIdentifier(c, checked_name); } fn transCreateNodeTypedef( - rp: RestorePoint, + c: *Context, typedef_decl: *const clang.TypedefNameDecl, toplevel: bool, checked_name: []const u8, -) Error!?*ast.Node { - const visib_tok = if (toplevel) try appendToken(rp.c, .Keyword_pub, "pub") else null; - const mut_tok = try appendToken(rp.c, .Keyword_const, "const"); - const name_tok = try appendIdentifier(rp.c, checked_name); - const eq_token = try appendToken(rp.c, .Equal, "="); +) Error!?Node { const child_qt = typedef_decl.getUnderlyingType(); const typedef_loc = typedef_decl.getLocation(); - const init_node = transQualType(rp, child_qt, typedef_loc) catch |err| switch (err) { + const init_node = transQualType(c, child_qt, typedef_loc) catch |err| switch (err) { error.UnsupportedType => { - try failDecl(rp.c, typedef_loc, checked_name, "unable to resolve typedef child type", .{}); + try failDecl(c, typedef_loc, checked_name, "unable to resolve typedef child type", .{}); return null; }, error.OutOfMemory => |e| return e, }; - const semicolon_token = try appendToken(rp.c, .Semicolon, ";"); - const node = try ast.Node.VarDecl.create(rp.c.arena, .{ - .name_token = name_tok, - .mut_token = mut_tok, - .semicolon_token = semicolon_token, - }, .{ - .visib_token = visib_tok, - .eq_token = eq_token, - .init_node = init_node, - }); - return &node.base; + const payload = try c.arena.create(ast.Payload.Typedef); + payload.* = .{ + .base = .{ .tag = ([2]ast.Node.Tag{ .typedef, .pub_typedef })[toplevel] }, + .data = .{ + .name = checked_name, + .init = init_node, + }, + }; + return Node.initPayload(&payload.base); } fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?*ast.Node { @@ -1399,13 +1339,15 @@ fn transBinaryOperator( const lhs_uncasted = try transExpr(c, scope, stmt.getLHS(), .used, .l_value); const rhs_uncasted = try transExpr(c, scope, stmt.getRHS(), .used, .r_value); - const lhs = if (isBoolRes(lhs_uncasted)) + const lhs = if (isBoolRes(lhs_uncasted)) try Node.bool_to_int.create(c.arena, lhs_uncasted) - else lhs_uncasted; + else + lhs_uncasted; - const rhs = if (isBoolRes(rhs_uncasted)) + const rhs = if (isBoolRes(rhs_uncasted)) try Node.bool_to_int.create(c.arena, rhs_uncasted) - else rhs_uncasted; + else + rhs_uncasted; const payload = try c.arena.create(ast.Payload.BinOp); payload.* = .{ @@ -1415,7 +1357,7 @@ fn transBinaryOperator( .rhs = rhs, }, }; - return maybeSuppressResult(c, scope, used, &payload.base); + return maybeSuppressResult(c, scope, used, Node.initPayload(&payload.base)); } fn transCompoundStmtInline( @@ -1459,13 +1401,11 @@ fn transCStyleCastExprClass( } fn transDeclStmtOne( - rp: RestorePoint, + c: *Context, scope: *Scope, decl: *const clang.Decl, block_scope: *Scope.Block, -) TransError!*ast.Node { - const c = rp.c; - +) TransError!Node { switch (decl.getKind()) { .Var => { const var_decl = @ptrCast(*const clang.VarDecl, decl); @@ -1479,47 +1419,38 @@ fn transDeclStmtOne( .Extern, .Static => { // This is actually a global variable, put it in the global scope and reference it. // `_ = mangled_name;` - try visitVarDecl(rp.c, var_decl, mangled_name); - return try maybeSuppressResult(rp, scope, .unused, try transCreateNodeIdentifier(rp.c, mangled_name)); + try visitVarDecl(c, var_decl, mangled_name); + return try maybeSuppressResult(c, scope, .unused, try Node.identifier.create(c.arena, mangled_name)); }, else => {}, } - const mut_tok = if (qual_type.isConstQualified()) - try appendToken(c, .Keyword_const, "const") - else - try appendToken(c, .Keyword_var, "var"); - const name_tok = try appendIdentifier(c, mangled_name); + const is_const = qual_type.isConstQualified(); - _ = try appendToken(c, .Colon, ":"); const loc = decl.getLocation(); - const type_node = try transQualTypeMaybeInitialized(rp, qual_type, decl_init, loc); + const type_node = try transQualTypeMaybeInitialized(c, qual_type, decl_init, loc); - const eq_token = try appendToken(c, .Equal, "="); var init_node = if (decl_init) |expr| if (expr.getStmtClass() == .StringLiteralClass) - try transStringLiteralAsArray(rp, scope, @ptrCast(*const clang.StringLiteral, expr), try zigArraySize(rp.c, type_node)) + try transStringLiteralAsArray(c, scope, @ptrCast(*const clang.StringLiteral, expr), try zigArraySize(c, type_node)) else - try transExprCoercing(rp, scope, expr, .used, .r_value) + try transExprCoercing(c, scope, expr, .used, .r_value) else try transCreateNodeUndefinedLiteral(c); if (!qualTypeIsBoolean(qual_type) and isBoolRes(init_node)) { - const builtin_node = try rp.c.createBuiltinCall("@boolToInt", 1); - builtin_node.params()[0] = init_node; - builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")"); - init_node = &builtin_node.base; + init_node = try Node.bool_to_int.create(c.arena, init_node); } - const semicolon_token = try appendToken(c, .Semicolon, ";"); - const node = try ast.Node.VarDecl.create(c.arena, .{ - .name_token = name_tok, - .mut_token = mut_tok, - .semicolon_token = semicolon_token, - }, .{ - .eq_token = eq_token, - .type_node = type_node, - .init_node = init_node, + return Node.var_decl.create(c.arena, .{ + .is_pub = false, + .is_const = is_const, + .is_extern = false, + .is_export = false, + .linksection_string = null, + .alignment = null, + .name = mangled_name, + .type = type_node, + .init = init_node, }); - return &node.base; }, .Typedef => { const typedef_decl = @ptrCast(*const clang.TypedefNameDecl, decl); @@ -1529,7 +1460,7 @@ fn transDeclStmtOne( const underlying_type = underlying_qual.getTypePtr(); const mangled_name = try block_scope.makeMangledName(c, name); - const node = (try transCreateNodeTypedef(rp, typedef_decl, false, mangled_name)) orelse + const node = (try transCreateNodeTypedef(c, typedef_decl, false, mangled_name)) orelse return error.UnsupportedTranslation; return node; }, @@ -1543,14 +1474,14 @@ fn transDeclStmtOne( } } -fn transDeclStmt(rp: RestorePoint, scope: *Scope, stmt: *const clang.DeclStmt) TransError!*ast.Node { - const block_scope = scope.findBlockScope(rp.c) catch unreachable; +fn transDeclStmt(c: *Context, scope: *Scope, stmt: *const clang.DeclStmt) TransError!Node { + const block_scope = scope.findBlockScope(c) catch unreachable; var it = stmt.decl_begin(); const end_it = stmt.decl_end(); assert(it != end_it); while (true) : (it += 1) { - const node = try transDeclStmtOne(rp, scope, it[0], block_scope); + const node = try transDeclStmtOne(c, scope, it[0], block_scope); if (it + 1 == end_it) { return node; @@ -1562,15 +1493,15 @@ fn transDeclStmt(rp: RestorePoint, scope: *Scope, stmt: *const clang.DeclStmt) T } fn transDeclRefExpr( - rp: RestorePoint, + c: *Context, scope: *Scope, expr: *const clang.DeclRefExpr, lrvalue: LRValue, -) TransError!*ast.Node { +) TransError!Node { const value_decl = expr.getDecl(); - const name = try rp.c.str(@ptrCast(*const clang.NamedDecl, value_decl).getName_bytes_begin()); + const name = try c.str(@ptrCast(*const clang.NamedDecl, value_decl).getName_bytes_begin()); const mangled_name = scope.getAlias(name); - return transCreateNodeIdentifier(rp.c, mangled_name); + return Node.identifier.create(c.arena, mangled_name); } fn transImplicitCastExpr( @@ -1642,52 +1573,29 @@ fn transImplicitCastExpr( } fn transBoolExpr( - rp: RestorePoint, + c: *Context, scope: *Scope, expr: *const clang.Expr, used: ResultUsed, lrvalue: LRValue, - grouped: bool, -) TransError!*ast.Node { +) TransError!Node { if (@ptrCast(*const clang.Stmt, expr).getStmtClass() == .IntegerLiteralClass) { var is_zero: bool = undefined; - if (!(@ptrCast(*const clang.IntegerLiteral, expr).isZero(&is_zero, rp.c.clang_context))) { - return revertAndWarn(rp, error.UnsupportedTranslation, expr.getBeginLoc(), "invalid integer literal", .{}); + if (!(@ptrCast(*const clang.IntegerLiteral, expr).isZero(&is_zero, c.clang_context))) { + return revertAndWarn(c, error.UnsupportedTranslation, expr.getBeginLoc(), "invalid integer literal", .{}); } - return try transCreateNodeBoolLiteral(rp.c, !is_zero); + return Node{ .tag = ([2]ast.Node.Tag{ .true_literal, .false_literal })[is_zero] }; } - const lparen = if (grouped) - try appendToken(rp.c, .LParen, "(") - else - undefined; - var res = try transExpr(rp, scope, expr, used, lrvalue); - + var res = try transExpr(c, scope, expr, used, lrvalue); if (isBoolRes(res)) { - if (!grouped and res.tag == .GroupedExpression) { - const group = @fieldParentPtr(ast.Node.GroupedExpression, "base", res); - res = group.expr; - // get zig fmt to work properly - tokenSlice(rp.c, group.lparen)[0] = ')'; - } return res; } - const ty = getExprQualType(rp.c, expr).getTypePtr(); - const node = try finishBoolExpr(rp, scope, expr.getBeginLoc(), ty, res, used); + const ty = getExprQualType(c, expr).getTypePtr(); + const node = try finishBoolExpr(c, scope, expr.getBeginLoc(), ty, res, used); - if (grouped) { - const rparen = try appendToken(rp.c, .RParen, ")"); - const grouped_expr = try rp.c.arena.create(ast.Node.GroupedExpression); - grouped_expr.* = .{ - .lparen = lparen, - .expr = node, - .rparen = rparen, - }; - return maybeSuppressResult(rp, scope, used, &grouped_expr.base); - } else { - return maybeSuppressResult(rp, scope, used, node); - } + return maybeSuppressResult(c, scope, used, node); } fn exprIsBooleanType(expr: *const clang.Expr) bool { @@ -1713,34 +1621,32 @@ fn exprIsNarrowStringLiteral(expr: *const clang.Expr) bool { } } -fn isBoolRes(res: *ast.Node) bool { - switch (res.tag) { - .BoolOr, - .BoolAnd, - .EqualEqual, - .BangEqual, - .LessThan, - .GreaterThan, - .LessOrEqual, - .GreaterOrEqual, - .BoolNot, - .BoolLiteral, +fn isBoolRes(res: Node) bool { + switch (res.tag()) { + .@"or", + .@"and", + .equal, + .note_equal, + .less_than, + .less_than_equal, + .greater_than, + .greater_than_equal, + .not, + .false_literal, + .true_literal, => return true, - - .GroupedExpression => return isBoolRes(@fieldParentPtr(ast.Node.GroupedExpression, "base", res).expr), - else => return false, } } fn finishBoolExpr( - rp: RestorePoint, + c: *Context, scope: *Scope, loc: clang.SourceLocation, ty: *const clang.Type, - node: *ast.Node, + node: Node, used: ResultUsed, -) TransError!*ast.Node { +) TransError!Node { switch (ty.getTypeClass()) { .Builtin => { const builtin_ty = @ptrCast(*const clang.BuiltinType, ty); @@ -1772,42 +1678,39 @@ fn finishBoolExpr( .WChar_S, .Float16, => { - const op_token = try appendToken(rp.c, .BangEqual, "!="); - const rhs_node = try transCreateNodeInt(rp.c, 0); - return transCreateNodeInfixOp(rp, scope, node, .BangEqual, op_token, rhs_node, used, false); + // node != 0 + return Node.not_equal.create(c.arena, .{ .lhs = node, .rhs = Node.zero_literal.init()}); }, .NullPtr => { - const op_token = try appendToken(rp.c, .EqualEqual, "=="); - const rhs_node = try transCreateNodeNullLiteral(rp.c); - return transCreateNodeInfixOp(rp, scope, node, .EqualEqual, op_token, rhs_node, used, false); + // node == null + return Node.equal.create(c.arena, .{ .lhs = node, .rhs = Node.null_literal.init()}); }, else => {}, } }, .Pointer => { - const op_token = try appendToken(rp.c, .BangEqual, "!="); - const rhs_node = try transCreateNodeNullLiteral(rp.c); - return transCreateNodeInfixOp(rp, scope, node, .BangEqual, op_token, rhs_node, used, false); + // node == null + return Node.equal.create(c.arena, .{ .lhs = node, .rhs = Node.null_literal.init()}); }, .Typedef => { const typedef_ty = @ptrCast(*const clang.TypedefType, ty); const typedef_decl = typedef_ty.getDecl(); const underlying_type = typedef_decl.getUnderlyingType(); - return finishBoolExpr(rp, scope, loc, underlying_type.getTypePtr(), node, used); + return finishBoolExpr(c, scope, loc, underlying_type.getTypePtr(), node, used); }, .Enum => { - const op_token = try appendToken(rp.c, .BangEqual, "!="); - const rhs_node = try transCreateNodeInt(rp.c, 0); - return transCreateNodeInfixOp(rp, scope, node, .BangEqual, op_token, rhs_node, used, false); + // node != 0 + return Node.not_equal.create(c.arena, .{ .lhs = node, .rhs = Node.zero_literal.init()}); + const op_token = try appendToken(c, .BangEqual, "!="); }, .Elaborated => { const elaborated_ty = @ptrCast(*const clang.ElaboratedType, ty); const named_type = elaborated_ty.getNamedType(); - return finishBoolExpr(rp, scope, loc, named_type.getTypePtr(), node, used); + return finishBoolExpr(c, scope, loc, named_type.getTypePtr(), node, used); }, else => {}, } - return revertAndWarn(rp, error.UnsupportedType, loc, "unsupported bool expression type", .{}); + return fail(c, error.UnsupportedType, loc, "unsupported bool expression type", .{}); } const SuppressCast = enum { @@ -4242,7 +4145,7 @@ fn transCreateNodeBoolInfixOp( .rhs = rhs, }, }; - return maybeSuppressResult(c, scope, used, &payload.base); + return maybeSuppressResult(c, scope, used, Node.initPayload(&payload.base)); } fn transCreateNodePtrType( @@ -4654,7 +4557,7 @@ fn transCreateNodeShiftOp( const lhs = try transExpr(c, scope, lhs_expr, .used, .l_value); const rhs_type = try qualTypeToLog2IntRef(c, stmt.getType(), rhs_location); - const rhs = try transExpr(c, scope, rhs_expr, .used, .r_value); + const rhs = try transExprCoercing(c, scope, rhs_expr, .used, .r_value); const rhs_casted = try Node.int_cast.create(c.arena, .{ .lhs = rhs_type, .rhs = rhs_type }); const payload = try c.arena.create(ast.Payload.BinOp); @@ -4663,9 +4566,9 @@ fn transCreateNodeShiftOp( .data = .{ .lhs = lhs, .rhs = rhs_casted, - } + }, }; - return &payload.base; + return Node.initPayload(&payload.base); } fn transCreateNodePtrDeref(c: *Context, lhs: *ast.Node) !*ast.Node { @@ -4961,7 +4864,7 @@ fn finishTransFnProto( }; } - const link_section_string: ?[]const u8 = blk: { + const linksection_string = blk: { if (fn_decl) |decl| { var str_len: usize = undefined; if (decl.getSectionAttribute(&str_len)) |str_ptr| { @@ -5004,24 +4907,19 @@ fn finishTransFnProto( } }; - const fn_proto = try c.arena.create(ast.Payload.Func); - fn_proto.* = .{ - .base = .{ .tag = .func }, - .data = .{ - .is_pub = is_pub, - .is_extern = is_extern, - .is_export = is_export, - .is_var_args = is_var_args, - .name = name, - .link_section_string = link_section_string, - .explicit_callconv = explicit_callconv, - .params = c.arena.dupe(ast.Payload.Func.Param, fn_params.items), - .return_type = return_node, - .body = null, - .alignment = alignment, - }, - }; - return fn_proto; + return Node.func.create(c.arena, .{ + .is_pub = is_pub, + .is_extern = is_extern, + .is_export = is_export, + .is_var_args = is_var_args, + .name = name, + .linksection_string = linksection_string, + .explicit_callconv = explicit_callconv, + .params = try c.arena.dupe(ast.Payload.Func.Param, fn_params.items), + .return_type = return_node, + .body = null, + .alignment = alignment, + }); } fn warn(c: *Context, scope: *Scope, loc: clang.SourceLocation, comptime format: []const u8, args: anytype) !void { @@ -5054,6 +4952,19 @@ pub fn freeErrors(errors: []ClangErrMsg) void { errors.ptr.delete(errors.len); } +fn isZigPrimitiveType(name: []const u8) bool { + if (name.len > 1 and (name[0] == 'u' or name[0] == 'i')) { + for (name[1..]) |c| { + switch (c) { + '0'...'9' => {}, + else => return false, + } + } + return true; + } + return @import("astgen.zig").simple_types.has(name); +} + const MacroCtx = struct { source: []const u8, list: []const CToken, diff --git a/src/translate_c/ast.zig b/src/translate_c/ast.zig index 825d36add1..9abfe215e6 100644 --- a/src/translate_c/ast.zig +++ b/src/translate_c/ast.zig @@ -137,11 +137,16 @@ pub const Node = extern union { single_pointer, array_type, - + /// @import("std").mem.zeroes(T) + std_mem_zeroes, // pub const name = @compileError(msg); fail_decl, // var actual = mangled; arg_redecl, + /// const name = init; + typedef, + /// pub const name = init; + pub_typedef, pub const last_no_payload_tag = Tag.usingnamespace_builtins; pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1; @@ -257,11 +262,11 @@ pub const Node = extern union { .container_init => Payload.ContainerInit, .std_meta_cast => Payload.Infix, .block => Payload.Block, - .c_pointer => Payload.Pointer, - .single_pointer => Payload.Pointer, + .c_pointer, .single_pointer => Payload.Pointer, .array_type => Payload.Array, .arg_redecl => Payload.ArgRedecl, .log2_int_type => Payload.Log2IntType, + .typedef, .pub_typedef => Payload.Typedef, }; } @@ -301,6 +306,11 @@ pub const Node = extern union { return null; } + + pub fn initPayload(payload: *Payload) Node { + assert(@enumToInt(payload.tag) >= Tag.no_payload_count); + return .{ .ptr_otherwise = payload }; + } }; pub const Payload = struct { @@ -383,13 +393,15 @@ pub const Payload = struct { pub const VarDecl = struct { base: Node = .{ .tag = .var_decl }, data: struct { - @"pub": bool, - @"const": bool, - @"extern": bool, - @"export": bool, + is_pub: bool, + is_const: bool, + is_extern: bool, + is_export: bool, + alignment: ?c_uint, + linksection_string: ?[]const u8, name: []const u8, - type: Type, - init: Node, + type: Node, + init: ?Node, }, }; @@ -401,12 +413,12 @@ pub const Payload = struct { is_export: bool, is_var_args: bool, name: []const u8, - link_section_string: ?[]const u8, + linksection_string: ?[]const u8, explicit_callconv: ?std.builtin.CallingConvention, params: []Param, return_type: Node, body: ?Node, - alignment: c_uint, + alignment: ?c_uint, pub const Param = struct { is_noalias: bool, @@ -501,6 +513,14 @@ pub const Payload = struct { base: Node, data: std.math.Log2Int(u64), }; + + pub const Typedef = struct { + base: Node, + data: struct { + name: []const u8, + init: Node, + }, + }; }; /// Converts the nodes into a Zig ast. |
