diff --git a/src/translate_c.zig b/src/translate_c.zig index 3181f05f78..0bef2cb843 100644 --- a/src/translate_c.zig +++ b/src/translate_c.zig @@ -1084,7 +1084,6 @@ fn transStmt( const source_expr = @ptrCast(*const clang.OpaqueValueExpr, stmt).getSourceExpr().?; const expr = try transExpr(c, scope, source_expr, .used, lrvalue); return maybeSuppressResult(c, scope, result_used, expr); - const node = try c.arena.create(Node.GroupedExpression); }, else => { return revertAndWarn( @@ -1389,62 +1388,56 @@ fn transDeclRefExpr( } fn transImplicitCastExpr( - rp: RestorePoint, + c: *Context, scope: *Scope, expr: *const clang.ImplicitCastExpr, result_used: ResultUsed, -) TransError!*ast.Node { - const c = rp.c; +) TransError!Node { const sub_expr = expr.getSubExpr(); const dest_type = getExprQualType(c, @ptrCast(*const clang.Expr, expr)); const src_type = getExprQualType(c, sub_expr); switch (expr.getCastKind()) { .BitCast, .FloatingCast, .FloatingToIntegral, .IntegralToFloating, .IntegralCast, .PointerToIntegral, .IntegralToPointer => { - const sub_expr_node = try transExpr(rp, scope, sub_expr, .used, .r_value); - return try transCCast(rp, scope, expr.getBeginLoc(), dest_type, src_type, sub_expr_node); + const sub_expr_node = try transExpr(c, scope, sub_expr, .used, .r_value); + const casted = try transCCast(c, scope, expr.getBeginLoc(), dest_type, src_type, sub_expr_node); + return maybeSuppressResult(c, scope, result_used, casted); }, .LValueToRValue, .NoOp, .FunctionToPointerDecay => { - const sub_expr_node = try transExpr(rp, scope, sub_expr, .used, .r_value); - return maybeSuppressResult(rp, scope, result_used, sub_expr_node); + const sub_expr_node = try transExpr(c, scope, sub_expr, .used, .r_value); + return maybeSuppressResult(c, scope, result_used, sub_expr_node); }, .ArrayToPointerDecay => { if (exprIsNarrowStringLiteral(sub_expr)) { - const sub_expr_node = try transExpr(rp, scope, sub_expr, .used, .r_value); - return maybeSuppressResult(rp, scope, result_used, sub_expr_node); + const sub_expr_node = try transExpr(c, scope, sub_expr, .used, .r_value); + return maybeSuppressResult(c, scope, result_used, sub_expr_node); } - const prefix_op = try transCreateNodeSimplePrefixOp(rp.c, .AddressOf, .Ampersand, "&"); - prefix_op.rhs = try transExpr(rp, scope, sub_expr, .used, .r_value); - - return maybeSuppressResult(rp, scope, result_used, &prefix_op.base); + const addr = try Node.address_of.create(c.arena, try transExpr(c, scope, sub_expr, .used, .r_value)); + return maybeSuppressResult(c, scope, result_used, addr); }, .NullToPointer => { - return try transCreateNodeNullLiteral(rp.c); + return Node.null_literal.init(); }, .PointerToBoolean => { // @ptrToInt(val) != 0 - const ptr_to_int = try rp.c.createBuiltinCall("@ptrToInt", 1); - ptr_to_int.params()[0] = try transExpr(rp, scope, sub_expr, .used, .r_value); - ptr_to_int.rparen_token = try appendToken(rp.c, .RParen, ")"); + const ptr_to_int = try Node.ptr_to_int.create(c.arena, try transExpr(c, scope, sub_expr, .used, .r_value)); - const op_token = try appendToken(rp.c, .BangEqual, "!="); - const rhs_node = try transCreateNodeInt(rp.c, 0); - return transCreateNodeInfixOp(rp, scope, &ptr_to_int.base, .BangEqual, op_token, rhs_node, result_used, false); + const ne = try Node.not_equal.create(c.arena, .{ .lhs = ptr_to_int, .rhs = Node.zero_literal.init() }); + return maybeSuppressResult(c, scope, result_used, ne); }, .IntegralToBoolean => { - const sub_expr_node = try transExpr(rp, scope, sub_expr, .used, .r_value); + const sub_expr_node = try transExpr(c, scope, sub_expr, .used, .r_value); // The expression is already a boolean one, return it as-is if (isBoolRes(sub_expr_node)) - return sub_expr_node; + return maybeSuppressResult(c, scope, result_used, sub_expr_node); // val != 0 - const op_token = try appendToken(rp.c, .BangEqual, "!="); - const rhs_node = try transCreateNodeInt(rp.c, 0); - return transCreateNodeInfixOp(rp, scope, sub_expr_node, .BangEqual, op_token, rhs_node, result_used, false); + const ne = try Node.not_equal.create(c.arena, .{ .lhs = sub_expr_node, .rhs = Node.zero_literal.init() }); + return maybeSuppressResult(c, scope, result_used, ne); }, .BuiltinFnToFnPtr => { - return transExpr(rp, scope, sub_expr, .used, .r_value); + return transExpr(rp, scope, sub_expr, result_used, .r_value); }, else => |kind| return revertAndWarn( rp, @@ -1468,12 +1461,12 @@ fn transBoolExpr( if (!(@ptrCast(*const clang.IntegerLiteral, expr).isZero(&is_zero, c.clang_context))) { return revertAndWarn(c, error.UnsupportedTranslation, expr.getBeginLoc(), "invalid integer literal", .{}); } - return Node{ .tag = ([2]ast.Node.Tag{ .true_literal, .false_literal })[is_zero] }; + return Node{ .tag = ([2]ast.Node.Tag{ .true_literal, .false_literal })[@boolToInt(is_zero)] }; } var res = try transExpr(c, scope, expr, used, lrvalue); if (isBoolRes(res)) { - return res; + return maybeSuppressResult(c, scope, used, res); } const ty = getExprQualType(c, expr).getTypePtr(); @@ -1563,18 +1556,18 @@ fn finishBoolExpr( .Float16, => { // node != 0 - return Node.not_equal.create(c.arena, .{ .lhs = node, .rhs = Node.zero_literal.init()}); + return Node.not_equal.create(c.arena, .{ .lhs = node, .rhs = Node.zero_literal.init() }); }, .NullPtr => { // node == null - return Node.equal.create(c.arena, .{ .lhs = node, .rhs = Node.null_literal.init()}); + return Node.equal.create(c.arena, .{ .lhs = node, .rhs = Node.null_literal.init() }); }, else => {}, } }, .Pointer => { // node == null - return Node.equal.create(c.arena, .{ .lhs = node, .rhs = Node.null_literal.init()}); + return Node.equal.create(c.arena, .{ .lhs = node, .rhs = Node.null_literal.init() }); }, .Typedef => { const typedef_ty = @ptrCast(*const clang.TypedefType, ty); @@ -1584,7 +1577,7 @@ fn finishBoolExpr( }, .Enum => { // node != 0 - return Node.not_equal.create(c.arena, .{ .lhs = node, .rhs = Node.zero_literal.init()}); + return Node.not_equal.create(c.arena, .{ .lhs = node, .rhs = Node.zero_literal.init() }); const op_token = try appendToken(c, .BangEqual, "!="); }, .Elaborated => { @@ -1653,11 +1646,11 @@ fn transReturnStmt( } fn transStringLiteral( - rp: RestorePoint, + c: *Context, scope: *Scope, stmt: *const clang.StringLiteral, result_used: ResultUsed, -) TransError!*ast.Node { +) TransError!Node { const kind = stmt.getKind(); switch (kind) { .Ascii, .UTF8 => { @@ -1665,55 +1658,28 @@ fn transStringLiteral( const bytes_ptr = stmt.getString_bytes_begin_size(&len); const str = bytes_ptr[0..len]; - const token = try appendTokenFmt(rp.c, .StringLiteral, "\"{}\"", .{std.zig.fmtEscapes(str)}); - const node = try rp.c.arena.create(ast.Node.OneToken); - node.* = .{ - .base = .{ .tag = .StringLiteral }, - .token = token, - }; - return maybeSuppressResult(rp, scope, result_used, &node.base); + const str = try std.fmt.allocPrint(c.arena, "\"{}\"", .{std.zig.fmtEscapes(str)}); + const node = try Node.string_literal.create(c.arena, str); + return maybeSuppressResult(c, scope, result_used, node); }, .UTF16, .UTF32, .Wide => { - const node = try transWideStringLiteral(rp, scope, stmt); - return maybeSuppressResult(rp, scope, result_used, node); + const str_type = @tagName(stmt.getKind()); + const name = try std.fmt.allocPrint(c.arena, "zig.{s}_string_{d}", .{ str_type, c.getMangle() }); + const lit_array = try transStringLiteralAsArray(c, scope, stmt, stmt.getLength() + 1); + + const decl = try Node.var_simple.create(c.arena, .{ .name = name, .init = lit_array }); + try scope.appendNode(name, decl); + const node = try Node.identifier.create(c.arena, name); + return maybeSuppressResult(c, scope, result_used, node); }, } } -/// Translates a wide string literal as a global "anonymous" array of the relevant-sized -/// integer type + null terminator, and returns an identifier node for it -fn transWideStringLiteral(rp: RestorePoint, scope: *Scope, stmt: *const clang.StringLiteral) TransError!*ast.Node { - const str_type = @tagName(stmt.getKind()); - const mangle = rp.c.getMangle(); - const name = try std.fmt.allocPrint(rp.c.arena, "zig.{s}_string_{d}", .{ str_type, mangle }); - - const const_tok = try appendToken(rp.c, .Keyword_const, "const"); - const name_tok = try appendIdentifier(rp.c, name); - const eq_tok = try appendToken(rp.c, .Equal, "="); - var semi_tok: ast.TokenIndex = undefined; - - const lit_array = try transStringLiteralAsArray(rp, scope, stmt, stmt.getLength() + 1); - - semi_tok = try appendToken(rp.c, .Semicolon, ";"); - const var_decl_node = try ast.Node.VarDecl.create(rp.c.arena, .{ - .name_token = name_tok, - .mut_token = const_tok, - .semicolon_token = semi_tok, - }, .{ - .visib_token = null, - .eq_token = eq_tok, - .init_node = lit_array, - }); - try addTopLevelDecl(rp.c, name, &var_decl_node.base); - return transCreateNodeIdentifier(rp.c, name); -} - /// Parse the size of an array back out from an ast Node. -fn zigArraySize(c: *Context, node: *ast.Node) TransError!usize { - if (node.castTag(.ArrayType)) |array| { - if (array.len_expr.castTag(.IntegerLiteral)) |int_lit| { - const tok = tokenSlice(c, int_lit.token); - return std.fmt.parseUnsigned(usize, tok, 10) catch error.UnsupportedTranslation; +fn zigArraySize(c: *Context, node: Node) TransError!usize { + if (node.castTag(.array_type)) |array| { + if (array.data.len.castTag(.int_literal)) |int_lit| { + return std.fmt.parseUnsigned(usize, int_lit.data, 10) catch error.UnsupportedTranslation; } } return error.UnsupportedTranslation; @@ -1725,11 +1691,11 @@ fn zigArraySize(c: *Context, node: *ast.Node) TransError!usize { /// than the array, truncate the string. If the array is larger than the /// string literal, pad the array with 0's fn transStringLiteralAsArray( - rp: RestorePoint, + c: *Context, scope: *Scope, stmt: *const clang.StringLiteral, array_size: usize, -) TransError!*ast.Node { +) TransError!Node { if (array_size == 0) return error.UnsupportedType; const str_length = stmt.getLength(); @@ -1738,40 +1704,21 @@ fn transStringLiteralAsArray( const ty = expr_base.getType().getTypePtr(); const const_arr_ty = @ptrCast(*const clang.ConstantArrayType, ty); - const ty_node = try rp.c.arena.create(ast.Node.ArrayType); - const op_token = try appendToken(rp.c, .LBracket, "["); - const len_expr = try transCreateNodeInt(rp.c, array_size); - _ = try appendToken(rp.c, .RBracket, "]"); - - ty_node.* = .{ - .op_token = op_token, - .rhs = try transQualType(rp, const_arr_ty.getElementType(), expr_base.getBeginLoc()), - .len_expr = len_expr, - }; - _ = try appendToken(rp.c, .LBrace, "{"); - var init_node = try ast.Node.ArrayInitializer.alloc(rp.c.arena, array_size); - init_node.* = .{ - .lhs = &ty_node.base, - .rtoken = undefined, - .list_len = array_size, - }; - const init_list = init_node.list(); + const arr_type = try transQualType(c, const_arr_ty.getElementType(), expr_base.getBeginLoc()); + const init_list = try c.arena.alloc(Node, array_size); var i: c_uint = 0; const kind = stmt.getKind(); const narrow = kind == .Ascii or kind == .UTF8; while (i < str_length and i < array_size) : (i += 1) { const code_unit = stmt.getCodeUnit(i); - init_list[i] = try transCreateCharLitNode(rp.c, narrow, code_unit); - _ = try appendToken(rp.c, .Comma, ","); + init_list[i] = try transCreateCharLitNode(c, narrow, code_unit); } while (i < array_size) : (i += 1) { - init_list[i] = try transCreateNodeInt(rp.c, 0); - _ = try appendToken(rp.c, .Comma, ","); + init_list[i] = try transCreateNodeInt(c, 0); } - init_node.rtoken = try appendToken(rp.c, .RBrace, "}"); - return &init_node.base; + return Node.array_init.create(c.arena, init_list); } fn cIsEnum(qt: clang.QualType) bool { @@ -1790,152 +1737,87 @@ fn cIntTypeForEnum(enum_qt: clang.QualType) clang.QualType { } fn transCCast( - rp: RestorePoint, + c: *Context, scope: *Scope, loc: clang.SourceLocation, dst_type: clang.QualType, src_type: clang.QualType, - expr: *ast.Node, -) !*ast.Node { + expr: Node, +) !Node { if (qualTypeCanon(dst_type).isVoidType()) return expr; if (dst_type.eq(src_type)) return expr; if (qualTypeIsPtr(dst_type) and qualTypeIsPtr(src_type)) - return transCPtrCast(rp, loc, dst_type, src_type, expr); + return transCPtrCast(c, loc, dst_type, src_type, expr); + + const dst_node = try transQualType(c, dst_type, loc); if (cIsInteger(dst_type) and (cIsInteger(src_type) or cIsEnum(src_type))) { // 1. If src_type is an enum, determine the underlying signed int type // 2. Extend or truncate without changing signed-ness. // 3. Bit-cast to correct signed-ness const src_type_is_signed = cIsSignedInteger(src_type) or cIsEnum(src_type); const src_int_type = if (cIsInteger(src_type)) src_type else cIntTypeForEnum(src_type); - var src_int_expr = if (cIsInteger(src_type)) expr else try transEnumToInt(rp.c, expr); - - // @bitCast(dest_type, intermediate_value) - const cast_node = try rp.c.createBuiltinCall("@bitCast", 2); - cast_node.params()[0] = try transQualType(rp, dst_type, loc); - _ = try appendToken(rp.c, .Comma, ","); + var src_int_expr = if (cIsInteger(src_type)) expr else Node.enum_to_int.create(c.arena, expr); if (isBoolRes(src_int_expr)) { - const bool_to_int_node = try rp.c.createBuiltinCall("@boolToInt", 1); - bool_to_int_node.params()[0] = src_int_expr; - bool_to_int_node.rparen_token = try appendToken(rp.c, .RParen, ")"); - src_int_expr = &bool_to_int_node.base; + src_int_expr = try Node.bool_to_int.create(c.arena, src_int_expr); } switch (cIntTypeCmp(dst_type, src_int_type)) { .lt => { // @truncate(SameSignSmallerInt, src_int_expr) - const trunc_node = try rp.c.createBuiltinCall("@truncate", 2); - const ty_node = try transQualTypeIntWidthOf(rp.c, dst_type, src_type_is_signed); - trunc_node.params()[0] = ty_node; - _ = try appendToken(rp.c, .Comma, ","); - trunc_node.params()[1] = src_int_expr; - trunc_node.rparen_token = try appendToken(rp.c, .RParen, ")"); - - cast_node.params()[1] = &trunc_node.base; + const ty_node = try transQualTypeIntWidthOf(c, dst_type, src_type_is_signed); + src_int_expr = try Node.truncate.create(c.arena, .{ .lhs = ty_node, .rhs = src_int_expr }); }, .gt => { // @as(SameSignBiggerInt, src_int_expr) - const as_node = try rp.c.createBuiltinCall("@as", 2); - const ty_node = try transQualTypeIntWidthOf(rp.c, dst_type, src_type_is_signed); - as_node.params()[0] = ty_node; - _ = try appendToken(rp.c, .Comma, ","); - as_node.params()[1] = src_int_expr; - as_node.rparen_token = try appendToken(rp.c, .RParen, ")"); - - cast_node.params()[1] = &as_node.base; + const ty_node = try transQualTypeIntWidthOf(c, dst_type, src_type_is_signed); + src_int_expr = try Node.as.create(c.arena, .{ .lhs = ty_node, .rhs = src_int_expr }); }, .eq => { - cast_node.params()[1] = src_int_expr; + // src_int_expr = src_int_expr }, } - cast_node.rparen_token = try appendToken(rp.c, .RParen, ")"); - return &cast_node.base; + // @bitCast(dest_type, intermediate_value) + return Node.bit_cast.create(c.arena, .{ .lhs = dst_node, .rhs = src_int_expr }); } if (cIsInteger(dst_type) and qualTypeIsPtr(src_type)) { // @intCast(dest_type, @ptrToInt(val)) - const cast_node = try rp.c.createBuiltinCall("@intCast", 2); - cast_node.params()[0] = try transQualType(rp, dst_type, loc); - _ = try appendToken(rp.c, .Comma, ","); - const builtin_node = try rp.c.createBuiltinCall("@ptrToInt", 1); - builtin_node.params()[0] = expr; - builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")"); - cast_node.params()[1] = &builtin_node.base; - cast_node.rparen_token = try appendToken(rp.c, .RParen, ")"); - return &cast_node.base; + const ptr_to_int = try Node.ptr_to_int.create(c.arena, expr); + return Node.int_cast.create(c.arena, .{ .lhs = dst_node, .rhs = ptr_to_int }); } if (cIsInteger(src_type) and qualTypeIsPtr(dst_type)) { // @intToPtr(dest_type, val) - const builtin_node = try rp.c.createBuiltinCall("@intToPtr", 2); - builtin_node.params()[0] = try transQualType(rp, dst_type, loc); - _ = try appendToken(rp.c, .Comma, ","); - builtin_node.params()[1] = expr; - builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")"); - return &builtin_node.base; + return Node.int_to_ptr.create(c.arena, .{ .lhs = dst_node, .rhs = expr }); } if (cIsFloating(src_type) and cIsFloating(dst_type)) { - const builtin_node = try rp.c.createBuiltinCall("@floatCast", 2); - builtin_node.params()[0] = try transQualType(rp, dst_type, loc); - _ = try appendToken(rp.c, .Comma, ","); - builtin_node.params()[1] = expr; - builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")"); - return &builtin_node.base; + // @floatCast(dest_type, val) + return Node.float_cast.create(c.arena, .{ .lhs = dst_node, .rhs = expr }); } if (cIsFloating(src_type) and !cIsFloating(dst_type)) { - const builtin_node = try rp.c.createBuiltinCall("@floatToInt", 2); - builtin_node.params()[0] = try transQualType(rp, dst_type, loc); - _ = try appendToken(rp.c, .Comma, ","); - builtin_node.params()[1] = expr; - builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")"); - return &builtin_node.base; + // @floatToInt(dest_type, val) + return Node.float_to_int.create(c.arena, .{ .lhs = dst_node, .rhs = expr }); } if (!cIsFloating(src_type) and cIsFloating(dst_type)) { - const builtin_node = try rp.c.createBuiltinCall("@intToFloat", 2); - builtin_node.params()[0] = try transQualType(rp, dst_type, loc); - _ = try appendToken(rp.c, .Comma, ","); - builtin_node.params()[1] = expr; - builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")"); - return &builtin_node.base; + // @intToFloat(dest_type, val) + return Node.int_to_float.create(c.arena, .{ .lhs = dst_node, .rhs = expr }); } if (qualTypeIsBoolean(src_type) and !qualTypeIsBoolean(dst_type)) { // @boolToInt returns either a comptime_int or a u1 // TODO: if dst_type is 1 bit & signed (bitfield) we need @bitCast // instead of @as - const builtin_node = try rp.c.createBuiltinCall("@boolToInt", 1); - builtin_node.params()[0] = expr; - builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")"); - - const as_node = try rp.c.createBuiltinCall("@as", 2); - as_node.params()[0] = try transQualType(rp, dst_type, loc); - _ = try appendToken(rp.c, .Comma, ","); - as_node.params()[1] = &builtin_node.base; - as_node.rparen_token = try appendToken(rp.c, .RParen, ")"); - - return &as_node.base; + const bool_to_int = Node.bool_to_int.create(c.arena, expr); + return Node.as.create(c.arena, .{ .lhs = dst_node, .rhs = bool_to_int }); } if (cIsEnum(dst_type)) { - const builtin_node = try rp.c.createBuiltinCall("@intToEnum", 2); - builtin_node.params()[0] = try transQualType(rp, dst_type, loc); - _ = try appendToken(rp.c, .Comma, ","); - builtin_node.params()[1] = expr; - builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")"); - return &builtin_node.base; + // @intToEnum(dest_type, val) + return Node.int_to_enum.create(c.arena, .{ .lhs = dst_node, .rhs = expr }); } if (cIsEnum(src_type) and !cIsEnum(dst_type)) { - return transEnumToInt(rp.c, expr); + // @enumToInt(val) + return Node.enum_to_int.create(c.arena, expr); } - const cast_node = try rp.c.createBuiltinCall("@as", 2); - cast_node.params()[0] = try transQualType(rp, dst_type, loc); - _ = try appendToken(rp.c, .Comma, ","); - cast_node.params()[1] = expr; - cast_node.rparen_token = try appendToken(rp.c, .RParen, ")"); - return &cast_node.base; -} - -fn transEnumToInt(c: *Context, enum_expr: *ast.Node) TypeError!*ast.Node { - const builtin_node = try c.createBuiltinCall("@enumToInt", 1); - builtin_node.params()[0] = enum_expr; - builtin_node.rparen_token = try appendToken(c, .RParen, ")"); - return &builtin_node.base; + // @as(dest_type, val) + return Node.as.create(c.arena, .{ .lhs = dst_node, .rhs = expr }); } fn transExpr( @@ -1976,13 +1858,12 @@ fn transExprCoercing( } fn transInitListExprRecord( - rp: RestorePoint, + c: *Context, scope: *Scope, loc: clang.SourceLocation, expr: *const clang.InitListExpr, ty: *const clang.Type, - used: ResultUsed, -) TransError!*ast.Node { +) TransError!Node { var is_union_type = false; // Unions and Structs are both represented as RecordDecl const record_ty = ty.getAsRecordType() orelse @@ -1994,13 +1875,11 @@ fn transInitListExprRecord( const record_def = record_decl.getDefinition() orelse unreachable; - const ty_node = try transType(rp, ty, loc); + const ty_node = try transType(c, ty, loc); const init_count = expr.getNumInits(); - var field_inits = std.ArrayList(*ast.Node).init(rp.c.gpa); + var field_inits = std.ArrayList(ast.Payload.ContainerInit.Initializer).init(c.gpa); defer field_inits.deinit(); - _ = try appendToken(rp.c, .LBrace, "{"); - var init_i: c_uint = 0; var it = record_def.field_begin(); const end_it = record_def.field_end(); @@ -2018,76 +1897,28 @@ fn transInitListExprRecord( // Generate the field assignment expression: // .field_name = expr - const period_tok = try appendToken(rp.c, .Period, "."); - - var raw_name = try rp.c.str(@ptrCast(*const clang.NamedDecl, field_decl).getName_bytes_begin()); + var raw_name = try c.str(@ptrCast(*const clang.NamedDecl, field_decl).getName_bytes_begin()); if (field_decl.isAnonymousStructOrUnion()) { - const name = rp.c.decl_table.get(@ptrToInt(field_decl.getCanonicalDecl())).?; - raw_name = try mem.dupe(rp.c.arena, u8, name); + const name = c.decl_table.get(@ptrToInt(field_decl.getCanonicalDecl())).?; + raw_name = try mem.dupe(c.arena, u8, name); } - const field_name_tok = try appendIdentifier(rp.c, raw_name); - _ = try appendToken(rp.c, .Equal, "="); - - const field_init_node = try rp.c.arena.create(ast.Node.FieldInitializer); - field_init_node.* = .{ - .period_token = period_tok, - .name_token = field_name_tok, - .expr = try transExpr(rp, scope, elem_expr, .used, .r_value), - }; - - try field_inits.append(&field_init_node.base); - _ = try appendToken(rp.c, .Comma, ","); + try field_inits.append(.{ + .name = raw_name, + .value = try transExpr(c, scope, elem_expr, .used, .r_value), + }); } - const node = try ast.Node.StructInitializer.alloc(rp.c.arena, field_inits.items.len); - node.* = .{ - .lhs = ty_node, - .rtoken = try appendToken(rp.c, .RBrace, "}"), - .list_len = field_inits.items.len, - }; - mem.copy(*ast.Node, node.list(), field_inits.items); - return &node.base; -} - -fn transCreateNodeArrayType( - rp: RestorePoint, - source_loc: clang.SourceLocation, - ty: *const clang.Type, - len: anytype, -) !*ast.Node { - const node = try rp.c.arena.create(ast.Node.ArrayType); - const op_token = try appendToken(rp.c, .LBracket, "["); - const len_expr = try transCreateNodeInt(rp.c, len); - _ = try appendToken(rp.c, .RBracket, "]"); - node.* = .{ - .op_token = op_token, - .rhs = try transType(rp, ty, source_loc), - .len_expr = len_expr, - }; - return &node.base; -} - -fn transCreateEmptyArray(rp: RestorePoint, loc: clang.SourceLocation, ty: *const clang.Type) TransError!*ast.Node { - const ty_node = try transCreateNodeArrayType(rp, loc, ty, 0); - _ = try appendToken(rp.c, .LBrace, "{"); - const filler_init_node = try ast.Node.ArrayInitializer.alloc(rp.c.arena, 0); - filler_init_node.* = .{ - .lhs = ty_node, - .rtoken = try appendToken(rp.c, .RBrace, "}"), - .list_len = 0, - }; - return &filler_init_node.base; + return Node.container_init.create(c.arena, try c.arena.dupe(ast.Payload.ContainerInit.Initializer, field_inits.items)); } fn transInitListExprArray( - rp: RestorePoint, + c: *Context, scope: *Scope, loc: clang.SourceLocation, expr: *const clang.InitListExpr, ty: *const clang.Type, - used: ResultUsed, -) TransError!*ast.Node { +) TransError!Node { const arr_type = ty.getAsArrayTypeUnsafe(); const child_qt = arr_type.getElementType(); const init_count = expr.getNumInits(); @@ -2098,111 +1929,67 @@ fn transInitListExprArray( const leftover_count = all_count - init_count; if (all_count == 0) { - return transCreateEmptyArray(rp, loc, child_qt.getTypePtr()); + return Node.empty_array.create(c.arena, try transQualType(c, child_qt, source_loc)); } + + const ty_node = try transType(ty); + const init_node = if (init_count != 0) blk: { + const init_list = try c.arena.alloc(Node, init_count); - var init_node: *ast.Node.ArrayInitializer = undefined; - var cat_tok: ast.TokenIndex = undefined; - if (init_count != 0) { - const ty_node = try transCreateNodeArrayType( - rp, - loc, - child_qt.getTypePtr(), - init_count, - ); - _ = try appendToken(rp.c, .LBrace, "{"); - init_node = try ast.Node.ArrayInitializer.alloc(rp.c.arena, init_count); - init_node.* = .{ - .lhs = ty_node, - .rtoken = undefined, - .list_len = init_count, - }; - const init_list = init_node.list(); - - var i: c_uint = 0; - while (i < init_count) : (i += 1) { + for (init_list) |*init, i| { const elem_expr = expr.getInit(i); - init_list[i] = try transExpr(rp, scope, elem_expr, .used, .r_value); - _ = try appendToken(rp.c, .Comma, ","); + init.* = try transExpr(c, scope, elem_expr, .used, .r_value); } - init_node.rtoken = try appendToken(rp.c, .RBrace, "}"); + const init_node = try Node.array_init.create(c.arena, init_list); if (leftover_count == 0) { - return &init_node.base; + return init_node; } - cat_tok = try appendToken(rp.c, .PlusPlus, "++"); - } + break :blk init_node; + } else null; - const ty_node = try transCreateNodeArrayType(rp, loc, child_qt.getTypePtr(), 1); - _ = try appendToken(rp.c, .LBrace, "{"); - const filler_init_node = try ast.Node.ArrayInitializer.alloc(rp.c.arena, 1); - filler_init_node.* = .{ - .lhs = ty_node, - .rtoken = undefined, - .list_len = 1, - }; const filler_val_expr = expr.getArrayFiller(); - filler_init_node.list()[0] = try transExpr(rp, scope, filler_val_expr, .used, .r_value); - filler_init_node.rtoken = try appendToken(rp.c, .RBrace, "}"); + const filler_node = try Node.array_filler.create(c.arena, .{ + .type = ty_node, + .filler = try transExpr(c, scope, filler_val_expr, .used, .r_value), + .count = leftover_count, + }); - const rhs_node = if (leftover_count == 1) - &filler_init_node.base - else blk: { - const mul_tok = try appendToken(rp.c, .AsteriskAsterisk, "**"); - const mul_node = try rp.c.arena.create(ast.Node.SimpleInfixOp); - mul_node.* = .{ - .base = .{ .tag = .ArrayMult }, - .op_token = mul_tok, - .lhs = &filler_init_node.base, - .rhs = try transCreateNodeInt(rp.c, leftover_count), - }; - break :blk &mul_node.base; - }; - - if (init_count == 0) { - return rhs_node; + if (init_node) |some| { + return Node.array_cat.create(c.arena, some, filler_node); + } else { + return filler_node; } - - const cat_node = try rp.c.arena.create(ast.Node.SimpleInfixOp); - cat_node.* = .{ - .base = .{ .tag = .ArrayCat }, - .op_token = cat_tok, - .lhs = &init_node.base, - .rhs = rhs_node, - }; - return &cat_node.base; } fn transInitListExpr( - rp: RestorePoint, + c: *Context, scope: *Scope, expr: *const clang.InitListExpr, used: ResultUsed, -) TransError!*ast.Node { - const qt = getExprQualType(rp.c, @ptrCast(*const clang.Expr, expr)); +) TransError!Node { + const qt = getExprQualType(c, @ptrCast(*const clang.Expr, expr)); var qual_type = qt.getTypePtr(); const source_loc = @ptrCast(*const clang.Expr, expr).getBeginLoc(); if (qual_type.isRecordType()) { - return transInitListExprRecord( + return maybeSuppressResult(c, scope, used, try transInitListExprRecord( rp, scope, source_loc, expr, qual_type, - used, - ); + )); } else if (qual_type.isArrayType()) { - return transInitListExprArray( + return maybeSuppressResult(c, scope, used, try transInitListExprArray( rp, scope, source_loc, expr, qual_type, - used, - ); + )); } else { - const type_name = rp.c.str(qual_type.getTypeClassName()); - return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported initlist type: '{s}'", .{type_name}); + const type_name = c.str(qual_type.getTypeClassName()); + return fail(c, error.UnsupportedType, source_loc, "unsupported initlist type: '{s}'", .{type_name}); } } @@ -2259,15 +2046,15 @@ fn transZeroInitExpr( } fn transImplicitValueInitExpr( - rp: RestorePoint, + c: *Context, scope: *Scope, expr: *const clang.Expr, used: ResultUsed, -) TransError!*ast.Node { +) TransError!Node { const source_loc = expr.getBeginLoc(); - const qt = getExprQualType(rp.c, expr); + const qt = getExprQualType(c, expr); const ty = qt.getTypePtr(); - return transZeroInitExpr(rp, scope, source_loc, ty); + return transZeroInitExpr(c, scope, source_loc, ty); } fn transIfStmt( diff --git a/src/translate_c/ast.zig b/src/translate_c/ast.zig index b926efdbef..8cf6cf74d5 100644 --- a/src/translate_c/ast.zig +++ b/src/translate_c/ast.zig @@ -104,6 +104,7 @@ pub const Node = extern union { bit_and, bit_or, bit_xor, + array_cat, log2_int_type, /// @import("std").math.Log2Int(operand) @@ -118,6 +119,24 @@ pub const Node = extern union { bool_to_int, /// @as(lhs, rhs) as, + /// @truncate(lhs, rhs) + truncate, + /// @bitCast(lhs, rhs) + bit_cast, + /// @floatCast(lhs, rhs) + float_cast, + /// @floatToInt(lhs, rhs) + float_to_int, + /// @intToFloat(lhs, rhs) + int_to_float, + /// @intToEnum(lhs, rhs) + int_to_enum, + /// @enumToInt(operand) + enum_to_int, + /// @intToPtr(lhs, rhs) + int_to_ptr, + /// @ptrToInt(operand) + ptr_to_int, negate, negate_wrap, @@ -154,6 +173,11 @@ pub const Node = extern union { /// pub const enum_field_name = @enumToInt(enum_name.field_name); enum_redecl, + /// [0]type{} + empty_array, + /// [1]type{val} ** count + array_filler, + pub const last_no_payload_tag = Tag.usingnamespace_builtins; pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1; @@ -184,6 +208,9 @@ pub const Node = extern union { .optional_type, .address_of, .unwrap_deref, + .ptr_to_int, + .enum_to_int, + .empty_array, => Payload.UnOp, .add, @@ -239,6 +266,14 @@ pub const Node = extern union { .int_cast, .bool_to_int, .as, + .truncate, + .bit_cast, + .float_cast, + .float_to_int, + .int_to_float, + .int_to_enum, + .int_to_ptr, + .array_cat, => Payload.BinOp, .int, @@ -274,6 +309,7 @@ pub const Node = extern union { .log2_int_type => Payload.Log2IntType, .typedef, .pub_typedef, .pub_var_simple => Payload.SimpleVarDecl, .enum_redecl => Payload.EnumRedecl, + .array_filler => Payload.ArrayFiller, }; } @@ -533,6 +569,15 @@ pub const Payload = struct { enum_name: []const u8, }, }; + + pub const ArrayFiller = struct { + base: Node, + data: struct { + type: Node, + filler: Node, + count: usize, + }, + }; }; /// Converts the nodes into a Zig ast.