Commit d8b9fca0b1
Changed files (2)
src
translate_c
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.
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 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;
- };
+ 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,
+ });
- 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(