diff --git a/src-self-hosted/clang.zig b/src-self-hosted/clang.zig index 2229324763..e640e3eadc 100644 --- a/src-self-hosted/clang.zig +++ b/src-self-hosted/clang.zig @@ -1,4 +1,3 @@ -pub const struct_ZigClangAPValue = @OpaqueType(); pub const struct_ZigClangAPSInt = @OpaqueType(); pub const struct_ZigClangAPFloat = @OpaqueType(); pub const struct_ZigClangASTContext = @OpaqueType(); @@ -928,3 +927,34 @@ pub extern fn ZigClangAttributedType_getEquivalentType(*const ZigClangAttributed pub extern fn ZigClangCStyleCastExpr_getBeginLoc(*const ZigClangCStyleCastExpr) ZigClangSourceLocation; pub extern fn ZigClangCStyleCastExpr_getSubExpr(*const ZigClangCStyleCastExpr) *const ZigClangExpr; pub extern fn ZigClangCStyleCastExpr_getType(*const ZigClangCStyleCastExpr) ZigClangQualType; + +pub const ZigClangExprEvalResult = struct_ZigClangExprEvalResult; +pub const struct_ZigClangExprEvalResult = extern struct { + HasSideEffects: bool, + HasUndefinedBehavior: bool, + SmallVectorImpl: ?*c_void, + Val: ZigClangAPValue, +}; + +pub const struct_ZigClangAPValue = extern struct { + Kind: ZigClangAPValue_ValueKind, + Data: [68]u8, // TODO: is there a way to statically assert that this matches the .h? +}; + +pub const ZigClangAPValue_ValueKind = extern enum { + ZigClangAPValue_ValueKind_Uninitialized, + ZigClangAPValue_ValueKind_Int, + ZigClangAPValue_ValueKind_Float, + ZigClangAPValue_ValueKind_ComplexInt, + ZigClangAPValue_ValueKind_ComplexFloat, + ZigClangAPValue_ValueKind_LValue, + ZigClangAPValue_ValueKind_Vector, + ZigClangAPValue_ValueKind_Array, + ZigClangAPValue_ValueKind_Struct, + ZigClangAPValue_ValueKind_Union, + ZigClangAPValue_ValueKind_MemberPointer, + ZigClangAPValue_ValueKind_AddrLabelDiff, +}; + +pub extern fn ZigClangIntegerLiteral_EvaluateAsInt(*const ZigClangIntegerLiteral, *ZigClangExprEvalResult, *const ZigClangASTContext) bool; +pub extern fn ZigClangIntegerLiteral_getBeginLoc(*const ZigClangIntegerLiteral) ZigClangSourceLocation; diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig index 6d64a28f1f..7e05df4f56 100644 --- a/src-self-hosted/translate_c.zig +++ b/src-self-hosted/translate_c.zig @@ -333,6 +333,7 @@ fn transStmt( .DeclStmtClass => return transDeclStmt(rp, scope, @ptrCast(*const ZigClangDeclStmt, stmt)), .DeclRefExprClass => return transDeclRefExpr(rp, scope, @ptrCast(*const ZigClangDeclRefExpr, stmt), lrvalue), .ImplicitCastExprClass => return transImplicitCastExpr(rp, scope, @ptrCast(*const ZigClangImplicitCastExpr, stmt), result_used), + .IntegerLiteralClass => return transIntegerLiteral(rp, scope, @ptrCast(*const ZigClangIntegerLiteral, stmt), result_used), else => { return revertAndWarn( rp, @@ -534,6 +535,26 @@ fn transImplicitCastExpr( } } +fn transIntegerLiteral( + rp: RestorePoint, + scope: *Scope, + expr: *const ZigClangIntegerLiteral, + result_used: ResultUsed, +) !TransResult { + var eval_result: ZigClangExprEvalResult = undefined; + if (!ZigClangIntegerLiteral_EvaluateAsInt(expr, &eval_result, rp.c.clang_context)) { + const loc = ZigClangIntegerLiteral_getBeginLoc(expr); + return revertAndWarn(rp, error.UnsupportedTranslation, loc, "invalid integer literal"); + } + const node = try transCreateNodeAPInt(rp.c, ZigClangAPValue_getInt(&eval_result.Val)); + const res = TransResult{ + .node = node, + .child_scope = scope, + .node_scope = scope, + }; + return maybeSuppressResult(rp, scope, result_used, res); +} + fn transCCast( rp: RestorePoint, scope: *Scope, @@ -547,14 +568,17 @@ fn transCCast( if (qualTypeIsPtr(dst_type) and qualTypeIsPtr(src_type)) return transCPtrCast(rp, loc, dst_type, src_type, expr); if (cIsUnsignedInteger(dst_type) and qualTypeIsPtr(src_type)) { - const builtin_node = try transCreateNodeBuiltinFnCall(rp.c, "ptrToInt"); + const builtin_node = try transCreateNodeBuiltinFnCall(rp.c, "@ptrToInt"); try builtin_node.params.push(expr); + builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")"); return &(try transCreateNodeFnCall(rp.c, try transQualType(rp, dst_type, loc), &builtin_node.base)).base; } if (cIsUnsignedInteger(src_type) and qualTypeIsPtr(dst_type)) { - const builtin_node = try transCreateNodeBuiltinFnCall(rp.c, "intToPtr"); + const builtin_node = try transCreateNodeBuiltinFnCall(rp.c, "@intToPtr"); try builtin_node.params.push(try transQualType(rp, dst_type, loc)); + _ = try appendToken(rp.c, .Comma, ","); try builtin_node.params.push(expr); + builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")"); return &builtin_node.base; } // TODO: maybe widen to increase size @@ -599,25 +623,28 @@ fn transCPtrCast( ) !*ast.Node { const ty = ZigClangQualType_getTypePtr(dst_type); const child_type = ZigClangType_getPointeeType(ty); - const dst_type_node = try transType(rp, ty, loc); - const child_type_node = try transQualType(rp, child_type, loc); // Implicit downcasting from higher to lower alignment values is forbidden, // use @alignCast to side-step this problem - const ptrcast_node = try transCreateNodeBuiltinFnCall(rp.c, "ptrCast"); + const ptrcast_node = try transCreateNodeBuiltinFnCall(rp.c, "@ptrCast"); + const dst_type_node = try transType(rp, ty, loc); try ptrcast_node.params.push(dst_type_node); + _ = try appendToken(rp.c, .Comma, ","); if (ZigClangType_isVoidType(qualTypeCanon(child_type))) { // void has 1-byte alignment, so @alignCast is not needed try ptrcast_node.params.push(expr); } else { - const alignof_node = try transCreateNodeBuiltinFnCall(rp.c, "alignOf"); + const alignof_node = try transCreateNodeBuiltinFnCall(rp.c, "@alignOf"); + const child_type_node = try transQualType(rp, child_type, loc); try alignof_node.params.push(child_type_node); - const aligncast_node = try transCreateNodeBuiltinFnCall(rp.c, "alignCast"); + const aligncast_node = try transCreateNodeBuiltinFnCall(rp.c, "@alignCast"); try aligncast_node.params.push(&alignof_node.base); + _ = try appendToken(rp.c, .Comma, ","); try aligncast_node.params.push(expr); try ptrcast_node.params.push(&aligncast_node.base); } + ptrcast_node.rparen_token = try appendToken(rp.c, .RParen, ")"); return &ptrcast_node.base; } @@ -740,17 +767,20 @@ fn cIsUnsignedInteger(qt: ZigClangQualType) bool { } fn transCreateNodeBuiltinFnCall(c: *Context, name: []const u8) !*ast.Node.BuiltinCall { + const builtin_token = try appendToken(c, .Builtin, name); + _ = try appendToken(c, .LParen, "("); const node = try c.a().create(ast.Node.BuiltinCall); node.* = ast.Node.BuiltinCall{ .base = ast.Node{ .id = .BuiltinCall }, - .builtin_token = try appendToken(c, .Builtin, name), + .builtin_token = builtin_token, .params = ast.Node.BuiltinCall.ParamList.init(c.a()), - .rparen_token = undefined, // TODO TokenIndex, + .rparen_token = undefined, // set after appending args }; return node; } fn transCreateNodeFnCall(c: *Context, fn_expr: *ast.Node, first_arg: *ast.Node) !*ast.Node.SuffixOp { + _ = try appendToken(c, .LParen, "("); const node = try c.a().create(ast.Node.SuffixOp); node.* = ast.Node.SuffixOp{ .base = ast.Node{ .id = .SuffixOp }, @@ -761,16 +791,23 @@ fn transCreateNodeFnCall(c: *Context, fn_expr: *ast.Node, first_arg: *ast.Node) .async_attr = null, }, }, - .rtoken = undefined, // TODO TokenIndex + .rtoken = try appendToken(c, .RParen, ")"), }; + try node.op.Call.params.push(first_arg); return node; } -fn transCreateNodePrefixOp(c: *Context, op: ast.Node.PrefixOp.Op, rhs: *ast.Node) !*ast.Node { +fn transCreateNodePrefixOp( + c: *Context, + op: ast.Node.PrefixOp.Op, + rhs: *ast.Node, + op_tok_id: std.zig.Token.Id, + bytes: []const u8, +) !*ast.Node { const node = try c.a().create(ast.Node.PrefixOp); node.* = ast.Node.PrefixOp{ .base = ast.Node{ .id = .PrefixOp }, - .op_token = undefined, // TODO TokenIndex, + .op_token = try appendToken(c, op_tok_id, bytes), .op = op, .rhs = rhs, }; @@ -783,11 +820,12 @@ fn transCreateNodePtrType( is_volatile: bool, rhs: *ast.Node, op_tok_id: std.zig.Token.Id, + bytes: []const u8, ) !*ast.Node { const node = try c.a().create(ast.Node.PrefixOp); node.* = ast.Node.PrefixOp{ .base = ast.Node{ .id = .PrefixOp }, - .op_token = try appendToken(c, op_tok_id, ""), // TODO TokenIndex, + .op_token = try appendToken(c, op_tok_id, bytes), .op = ast.Node.PrefixOp.Op{ .PtrType = ast.Node.PrefixOp.PtrInfo{ .allowzero_token = null, @@ -801,6 +839,15 @@ fn transCreateNodePtrType( return &node.base; } +fn transCreateNodeAPInt(c: *Context, int: ?*const ZigClangAPSInt) !*ast.Node { + const node = try c.a().create(ast.Node.IntegerLiteral); + node.* = ast.Node.IntegerLiteral{ + .base = ast.Node{ .id = .IntegerLiteral }, + .token = try appendToken(c, .IntegerLiteral, "3333333"), // TODO + }; + return &node.base; +} + const RestorePoint = struct { c: *Context, token_index: ast.TokenIndex, @@ -860,7 +907,7 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour const child_qt = ZigClangType_getPointeeType(ty); const child_node = try transQualType(rp, child_qt, source_loc); if (qualTypeChildIsFnProto(child_qt)) - return transCreateNodePrefixOp(rp.c, .OptionalType, child_node); + return transCreateNodePrefixOp(rp.c, .OptionalType, child_node, .QuestionMark, "?"); if (typeIsOpaque(rp.c, ZigClangQualType_getTypePtr(child_qt), source_loc)) { const pointer_node = try transCreateNodePtrType( rp.c, @@ -868,8 +915,9 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour ZigClangQualType_isVolatileQualified(child_qt), child_node, .Asterisk, + "*", ); - return transCreateNodePrefixOp(rp.c, .OptionalType, pointer_node); + return transCreateNodePrefixOp(rp.c, .OptionalType, pointer_node, .QuestionMark, "?"); } return transCreateNodePtrType( rp.c, @@ -877,6 +925,7 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour ZigClangQualType_isVolatileQualified(child_qt), child_node, .BracketStarCBracket, + "[*c]", ); }, else => { diff --git a/src/zig_clang.cpp b/src/zig_clang.cpp index 6283f7b67d..99b55dc59e 100644 --- a/src/zig_clang.cpp +++ b/src/zig_clang.cpp @@ -21,6 +21,7 @@ #include #include +#include #include #if __GNUC__ >= 8 @@ -1287,6 +1288,20 @@ static_assert((clang::StringLiteral::StringKind)ZigClangStringLiteral_StringKind static_assert((clang::StringLiteral::StringKind)ZigClangStringLiteral_StringKind_UTF16 == clang::StringLiteral::UTF16, ""); static_assert((clang::StringLiteral::StringKind)ZigClangStringLiteral_StringKind_UTF32 == clang::StringLiteral::UTF32, ""); +static_assert((clang::APValue::ValueKind)ZigClangAPValue_ValueKind_Uninitialized == clang::APValue::ValueKind::Uninitialized, ""); +static_assert((clang::APValue::ValueKind)ZigClangAPValue_ValueKind_Int == clang::APValue::ValueKind::Int, ""); +static_assert((clang::APValue::ValueKind)ZigClangAPValue_ValueKind_Float == clang::APValue::ValueKind::Float, ""); +static_assert((clang::APValue::ValueKind)ZigClangAPValue_ValueKind_ComplexInt == clang::APValue::ValueKind::ComplexInt, ""); +static_assert((clang::APValue::ValueKind)ZigClangAPValue_ValueKind_ComplexFloat == clang::APValue::ValueKind::ComplexFloat, ""); +static_assert((clang::APValue::ValueKind)ZigClangAPValue_ValueKind_LValue == clang::APValue::ValueKind::LValue, ""); +static_assert((clang::APValue::ValueKind)ZigClangAPValue_ValueKind_Vector == clang::APValue::ValueKind::Vector, ""); +static_assert((clang::APValue::ValueKind)ZigClangAPValue_ValueKind_Array == clang::APValue::ValueKind::Array, ""); +static_assert((clang::APValue::ValueKind)ZigClangAPValue_ValueKind_Struct == clang::APValue::ValueKind::Struct, ""); +static_assert((clang::APValue::ValueKind)ZigClangAPValue_ValueKind_Union == clang::APValue::ValueKind::Union, ""); +static_assert((clang::APValue::ValueKind)ZigClangAPValue_ValueKind_MemberPointer == clang::APValue::ValueKind::MemberPointer, ""); +static_assert((clang::APValue::ValueKind)ZigClangAPValue_ValueKind_AddrLabelDiff == clang::APValue::ValueKind::AddrLabelDiff, ""); + +static_assert(sizeof(ZigClangAPValue) == sizeof(clang::APValue), ""); static_assert(sizeof(ZigClangSourceLocation) == sizeof(clang::SourceLocation), ""); static ZigClangSourceLocation bitcast(clang::SourceLocation src) { @@ -1312,6 +1327,13 @@ static clang::QualType bitcast(ZigClangQualType src) { return dest; } +static_assert(sizeof(ZigClangExprEvalResult) == sizeof(clang::Expr::EvalResult), ""); +static ZigClangExprEvalResult bitcast(clang::Expr::EvalResult src) { + ZigClangExprEvalResult dest; + memcpy(&dest, static_cast(&src), sizeof(ZigClangExprEvalResult)); + return dest; +} + static_assert(sizeof(ZigClangAPValueLValueBase) == sizeof(clang::APValue::LValueBase), ""); static ZigClangAPValueLValueBase bitcast(clang::APValue::LValueBase src) { ZigClangAPValueLValueBase dest; @@ -1979,3 +2001,19 @@ struct ZigClangQualType ZigClangCStyleCastExpr_getType(const struct ZigClangCSty auto casted = reinterpret_cast(self); return bitcast(casted->getType()); } + +bool ZigClangIntegerLiteral_EvaluateAsInt(const struct ZigClangIntegerLiteral *self, struct ZigClangExprEvalResult *result, const struct ZigClangASTContext *ctx) { + auto casted_self = reinterpret_cast(self); + auto casted_ctx = reinterpret_cast(ctx); + clang::Expr::EvalResult eval_result; + if (!casted_self->EvaluateAsInt(eval_result, *casted_ctx)) { + return false; + } + *result = bitcast(eval_result); + return true; +} + +struct ZigClangSourceLocation ZigClangIntegerLiteral_getBeginLoc(const struct ZigClangIntegerLiteral *self) { + auto casted = reinterpret_cast(self); + return bitcast(casted->getBeginLoc()); +} diff --git a/src/zig_clang.h b/src/zig_clang.h index bfaa5867a4..6efdca89d8 100644 --- a/src/zig_clang.h +++ b/src/zig_clang.h @@ -30,6 +30,33 @@ struct ZigClangAPValueLValueBase { unsigned Version; }; +enum ZigClangAPValue_ValueKind { + ZigClangAPValue_ValueKind_Uninitialized, + ZigClangAPValue_ValueKind_Int, + ZigClangAPValue_ValueKind_Float, + ZigClangAPValue_ValueKind_ComplexInt, + ZigClangAPValue_ValueKind_ComplexFloat, + ZigClangAPValue_ValueKind_LValue, + ZigClangAPValue_ValueKind_Vector, + ZigClangAPValue_ValueKind_Array, + ZigClangAPValue_ValueKind_Struct, + ZigClangAPValue_ValueKind_Union, + ZigClangAPValue_ValueKind_MemberPointer, + ZigClangAPValue_ValueKind_AddrLabelDiff +}; + +struct ZigClangAPValue { + enum ZigClangAPValue_ValueKind Kind; + char Data[68]; // experimentally-derived size of clang::APValue::DataType +}; + +struct ZigClangExprEvalResult { + bool HasSideEffects; + bool HasUndefinedBehavior; + void *SmallVectorImpl; + ZigClangAPValue Val; +}; + struct ZigClangAPValue; struct ZigClangAPSInt; struct ZigClangAPFloat; @@ -889,4 +916,7 @@ ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangCStyleCastExpr_getBeginLoc(co ZIG_EXTERN_C const struct ZigClangExpr *ZigClangCStyleCastExpr_getSubExpr(const struct ZigClangCStyleCastExpr *); ZIG_EXTERN_C struct ZigClangQualType ZigClangCStyleCastExpr_getType(const struct ZigClangCStyleCastExpr *); +ZIG_EXTERN_C bool ZigClangIntegerLiteral_EvaluateAsInt(const struct ZigClangIntegerLiteral *, struct ZigClangExprEvalResult *, const struct ZigClangASTContext *); +ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangIntegerLiteral_getBeginLoc(const struct ZigClangIntegerLiteral *); + #endif