Merge branch 'hryx-translate-c-userland'
commit
5345044edf
|
@ -1,4 +1,5 @@
|
|||
pub const struct_ZigClangAPValue = @OpaqueType();
|
||||
const builtin = @import("builtin");
|
||||
|
||||
pub const struct_ZigClangAPSInt = @OpaqueType();
|
||||
pub const struct_ZigClangAPFloat = @OpaqueType();
|
||||
pub const struct_ZigClangASTContext = @OpaqueType();
|
||||
|
@ -723,6 +724,7 @@ pub extern fn ZigClangSourceLocation_eq(a: struct_ZigClangSourceLocation, b: str
|
|||
pub extern fn ZigClangTypedefType_getDecl(self: ?*const struct_ZigClangTypedefType) ?*const struct_ZigClangTypedefNameDecl;
|
||||
pub extern fn ZigClangTypedefNameDecl_getUnderlyingType(self: ?*const struct_ZigClangTypedefNameDecl) struct_ZigClangQualType;
|
||||
pub extern fn ZigClangQualType_getCanonicalType(self: struct_ZigClangQualType) struct_ZigClangQualType;
|
||||
pub extern fn ZigClangQualType_getTypeClass(self: struct_ZigClangQualType) ZigClangTypeClass;
|
||||
pub extern fn ZigClangQualType_getTypePtr(self: struct_ZigClangQualType) *const struct_ZigClangType;
|
||||
pub extern fn ZigClangQualType_addConst(self: [*c]struct_ZigClangQualType) void;
|
||||
pub extern fn ZigClangQualType_eq(self: struct_ZigClangQualType, arg1: struct_ZigClangQualType) bool;
|
||||
|
@ -730,6 +732,7 @@ pub extern fn ZigClangQualType_isConstQualified(self: struct_ZigClangQualType) b
|
|||
pub extern fn ZigClangQualType_isVolatileQualified(self: struct_ZigClangQualType) bool;
|
||||
pub extern fn ZigClangQualType_isRestrictQualified(self: struct_ZigClangQualType) bool;
|
||||
pub extern fn ZigClangType_getTypeClass(self: ?*const struct_ZigClangType) ZigClangTypeClass;
|
||||
pub extern fn ZigClangType_getPointeeType(self: ?*const struct_ZigClangType) struct_ZigClangQualType;
|
||||
pub extern fn ZigClangType_isVoidType(self: ?*const struct_ZigClangType) bool;
|
||||
pub extern fn ZigClangType_getTypeClassName(self: *const struct_ZigClangType) [*]const u8;
|
||||
pub extern fn ZigClangStmt_getBeginLoc(self: *const struct_ZigClangStmt) struct_ZigClangSourceLocation;
|
||||
|
@ -894,3 +897,77 @@ pub const ZigClangCompoundStmt_const_body_iterator = [*c]const *struct_ZigClangS
|
|||
|
||||
pub extern fn ZigClangCompoundStmt_body_begin(self: *const ZigClangCompoundStmt) ZigClangCompoundStmt_const_body_iterator;
|
||||
pub extern fn ZigClangCompoundStmt_body_end(self: *const ZigClangCompoundStmt) ZigClangCompoundStmt_const_body_iterator;
|
||||
|
||||
pub const ZigClangDeclStmt_const_decl_iterator = [*c]const *struct_ZigClangDecl;
|
||||
|
||||
pub extern fn ZigClangDeclStmt_decl_begin(self: *const ZigClangDeclStmt) ZigClangDeclStmt_const_decl_iterator;
|
||||
pub extern fn ZigClangDeclStmt_decl_end(self: *const ZigClangDeclStmt) ZigClangDeclStmt_const_decl_iterator;
|
||||
|
||||
pub extern fn ZigClangVarDecl_getType(self: ?*const struct_ZigClangVarDecl) struct_ZigClangQualType;
|
||||
pub extern fn ZigClangVarDecl_getInit(*const ZigClangVarDecl) ?*const ZigClangExpr;
|
||||
pub extern fn ZigClangVarDecl_getTLSKind(self: ?*const struct_ZigClangVarDecl) ZigClangVarDecl_TLSKind;
|
||||
pub const ZigClangVarDecl_TLSKind = extern enum {
|
||||
None,
|
||||
Static,
|
||||
Dynamic,
|
||||
};
|
||||
|
||||
pub extern fn ZigClangImplicitCastExpr_getBeginLoc(*const ZigClangImplicitCastExpr) ZigClangSourceLocation;
|
||||
pub extern fn ZigClangImplicitCastExpr_getCastKind(*const ZigClangImplicitCastExpr) ZigClangCK;
|
||||
pub extern fn ZigClangImplicitCastExpr_getSubExpr(*const ZigClangImplicitCastExpr) *const ZigClangExpr;
|
||||
|
||||
pub extern fn ZigClangArrayType_getElementType(*const ZigClangArrayType) ZigClangQualType;
|
||||
|
||||
pub extern fn ZigClangDeclRefExpr_getDecl(*const ZigClangDeclRefExpr) *const ZigClangValueDecl;
|
||||
|
||||
pub extern fn ZigClangParenType_getInnerType(*const ZigClangParenType) ZigClangQualType;
|
||||
|
||||
pub extern fn ZigClangElaboratedType_getNamedType(*const ZigClangElaboratedType) ZigClangQualType;
|
||||
|
||||
pub extern fn ZigClangAttributedType_getEquivalentType(*const ZigClangAttributedType) ZigClangQualType;
|
||||
|
||||
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: if (builtin.os == .windows) [52]u8 else [68]u8,
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
pub extern fn ZigClangReturnStmt_getRetValue(*const ZigClangReturnStmt) ?*const ZigClangExpr;
|
||||
|
||||
pub extern fn ZigClangBinaryOperator_getOpcode(*const ZigClangBinaryOperator) ZigClangBO;
|
||||
pub extern fn ZigClangBinaryOperator_getBeginLoc(*const ZigClangBinaryOperator) ZigClangSourceLocation;
|
||||
pub extern fn ZigClangBinaryOperator_getLHS(*const ZigClangBinaryOperator) *const ZigClangExpr;
|
||||
pub extern fn ZigClangBinaryOperator_getRHS(*const ZigClangBinaryOperator) *const ZigClangExpr;
|
||||
pub extern fn ZigClangBinaryOperator_getType(*const ZigClangBinaryOperator) ZigClangQualType;
|
||||
|
||||
pub extern fn ZigClangStringLiteral_getKind(*const ZigClangStringLiteral) ZigClangStringLiteral_StringKind;
|
||||
pub extern fn ZigClangStringLiteral_getString_bytes_begin_size(*const ZigClangStringLiteral, *usize) [*c]const u8;
|
||||
|
|
|
@ -20,7 +20,7 @@ pub const ClangErrMsg = Stage2ErrorMsg;
|
|||
|
||||
pub const Error = error{OutOfMemory};
|
||||
const TypeError = Error || error{UnsupportedType};
|
||||
const TransError = Error || error{UnsupportedTranslation};
|
||||
const TransError = TypeError || error{UnsupportedTranslation};
|
||||
|
||||
const DeclTable = std.HashMap(usize, void, addrHash, addrEql);
|
||||
|
||||
|
@ -107,6 +107,8 @@ const Context = struct {
|
|||
decl_table: DeclTable,
|
||||
global_scope: *Scope.Root,
|
||||
mode: Mode,
|
||||
ptr_params: std.BufSet,
|
||||
clang_context: *ZigClangASTContext,
|
||||
|
||||
fn a(c: *Context) *std.mem.Allocator {
|
||||
return &c.tree.arena_allocator.allocator;
|
||||
|
@ -183,6 +185,8 @@ pub fn translate(
|
|||
.decl_table = DeclTable.init(arena),
|
||||
.global_scope = try arena.create(Scope.Root),
|
||||
.mode = mode,
|
||||
.ptr_params = std.BufSet.init(arena),
|
||||
.clang_context = ZigClangASTUnit_getASTContext(ast_unit).?,
|
||||
};
|
||||
context.global_scope.* = Scope.Root{
|
||||
.base = Scope{
|
||||
|
@ -195,7 +199,7 @@ pub fn translate(
|
|||
return context.err;
|
||||
}
|
||||
|
||||
_ = try appendToken(&context, .Eof, "");
|
||||
tree.root_node.eof_token = try appendToken(&context, .Eof, "");
|
||||
tree.source = source_buffer.toOwnedSlice();
|
||||
if (false) {
|
||||
std.debug.warn("debug source:\n{}\n==EOF==\ntokens:\n", tree.source);
|
||||
|
@ -257,7 +261,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
|
|||
.storage_class = storage_class,
|
||||
.scope = &scope,
|
||||
.is_export = switch (storage_class) {
|
||||
.None => has_body,
|
||||
.None => has_body and c.mode != .import,
|
||||
.Extern, .Static => false,
|
||||
.PrivateExtern => return failDecl(c, fn_decl_loc, fn_name, "unsupported storage class: private extern"),
|
||||
.Auto => unreachable, // Not legal on functions
|
||||
|
@ -267,7 +271,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
|
|||
const proto_node = switch (ZigClangType_getTypeClass(fn_type)) {
|
||||
.FunctionProto => blk: {
|
||||
const fn_proto_type = @ptrCast(*const ZigClangFunctionProtoType, fn_type);
|
||||
break :blk transFnProto(rp, fn_proto_type, fn_decl_loc, decl_ctx) catch |err| switch (err) {
|
||||
break :blk transFnProto(rp, fn_proto_type, fn_decl_loc, decl_ctx, true) catch |err| switch (err) {
|
||||
error.UnsupportedType => {
|
||||
return failDecl(c, fn_decl_loc, fn_name, "unable to resolve prototype of function");
|
||||
},
|
||||
|
@ -276,7 +280,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
|
|||
},
|
||||
.FunctionNoProto => blk: {
|
||||
const fn_no_proto_type = @ptrCast(*const ZigClangFunctionType, fn_type);
|
||||
break :blk transFnNoProto(rp, fn_no_proto_type, fn_decl_loc, decl_ctx) catch |err| switch (err) {
|
||||
break :blk transFnNoProto(rp, fn_no_proto_type, fn_decl_loc, decl_ctx, true) catch |err| switch (err) {
|
||||
error.UnsupportedType => {
|
||||
return failDecl(c, fn_decl_loc, fn_name, "unable to resolve prototype of function");
|
||||
},
|
||||
|
@ -295,7 +299,9 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
|
|||
const body_stmt = ZigClangFunctionDecl_getBody(fn_decl);
|
||||
const result = transStmt(rp, scope, body_stmt, .unused, .r_value) catch |err| switch (err) {
|
||||
error.OutOfMemory => |e| return e,
|
||||
error.UnsupportedTranslation => return failDecl(c, fn_decl_loc, fn_name, "unable to translate function"),
|
||||
error.UnsupportedTranslation,
|
||||
error.UnsupportedType,
|
||||
=> return failDecl(c, fn_decl_loc, fn_name, "unable to translate function"),
|
||||
};
|
||||
assert(result.node.id == ast.Node.Id.Block);
|
||||
proto_node.body_node = result.node;
|
||||
|
@ -322,7 +328,15 @@ fn transStmt(
|
|||
) !TransResult {
|
||||
const sc = ZigClangStmt_getStmtClass(stmt);
|
||||
switch (sc) {
|
||||
.BinaryOperatorClass => return transBinaryOperator(rp, scope, @ptrCast(*const ZigClangBinaryOperator, stmt), result_used),
|
||||
.CompoundStmtClass => return transCompoundStmt(rp, scope, @ptrCast(*const ZigClangCompoundStmt, stmt)),
|
||||
.CStyleCastExprClass => return transCStyleCastExprClass(rp, scope, @ptrCast(*const ZigClangCStyleCastExpr, stmt), result_used, lrvalue),
|
||||
.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),
|
||||
.ReturnStmtClass => return transReturnStmt(rp, scope, @ptrCast(*const ZigClangReturnStmt, stmt)),
|
||||
.StringLiteralClass => return transStringLiteral(rp, scope, @ptrCast(*const ZigClangStringLiteral, stmt), result_used),
|
||||
else => {
|
||||
return revertAndWarn(
|
||||
rp,
|
||||
|
@ -335,6 +349,87 @@ fn transStmt(
|
|||
}
|
||||
}
|
||||
|
||||
fn transBinaryOperator(
|
||||
rp: RestorePoint,
|
||||
scope: *Scope,
|
||||
stmt: *const ZigClangBinaryOperator,
|
||||
result_used: ResultUsed,
|
||||
) TransError!TransResult {
|
||||
const op = ZigClangBinaryOperator_getOpcode(stmt);
|
||||
const qt = ZigClangBinaryOperator_getType(stmt);
|
||||
switch (op) {
|
||||
.PtrMemD, .PtrMemI, .Cmp => return revertAndWarn(
|
||||
rp,
|
||||
error.UnsupportedTranslation,
|
||||
ZigClangBinaryOperator_getBeginLoc(stmt),
|
||||
"TODO: handle more C binary operators: {}",
|
||||
op,
|
||||
),
|
||||
.Assign => return TransResult{
|
||||
.node = &(try transCreateNodeAssign(rp, scope, result_used, ZigClangBinaryOperator_getLHS(stmt), ZigClangBinaryOperator_getRHS(stmt))).base,
|
||||
.child_scope = scope,
|
||||
.node_scope = scope,
|
||||
},
|
||||
.Add => {
|
||||
const node = if (cIsUnsignedInteger(qt))
|
||||
try transCreateNodeInfixOp(rp, scope, stmt, .AddWrap, .PlusPercent, "+%", true)
|
||||
else
|
||||
try transCreateNodeInfixOp(rp, scope, stmt, .Add, .Plus, "+", true);
|
||||
return maybeSuppressResult(rp, scope, result_used, TransResult{
|
||||
.node = node,
|
||||
.child_scope = scope,
|
||||
.node_scope = scope,
|
||||
});
|
||||
},
|
||||
.Sub => {
|
||||
const node = if (cIsUnsignedInteger(qt))
|
||||
try transCreateNodeInfixOp(rp, scope, stmt, .SubWrap, .MinusPercent, "-%", true)
|
||||
else
|
||||
try transCreateNodeInfixOp(rp, scope, stmt, .Sub, .Minus, "-", true);
|
||||
return maybeSuppressResult(rp, scope, result_used, TransResult{
|
||||
.node = node,
|
||||
.child_scope = scope,
|
||||
.node_scope = scope,
|
||||
});
|
||||
},
|
||||
.Mul,
|
||||
.Div,
|
||||
.Rem,
|
||||
.Shl,
|
||||
.Shr,
|
||||
.LT,
|
||||
.GT,
|
||||
.LE,
|
||||
.GE,
|
||||
.EQ,
|
||||
.NE,
|
||||
.And,
|
||||
.Xor,
|
||||
.Or,
|
||||
.LAnd,
|
||||
.LOr,
|
||||
.Comma,
|
||||
=> return revertAndWarn(
|
||||
rp,
|
||||
error.UnsupportedTranslation,
|
||||
ZigClangBinaryOperator_getBeginLoc(stmt),
|
||||
"TODO: handle more C binary operators: {}",
|
||||
op,
|
||||
),
|
||||
.MulAssign,
|
||||
.DivAssign,
|
||||
.RemAssign,
|
||||
.AddAssign,
|
||||
.SubAssign,
|
||||
.ShlAssign,
|
||||
.ShrAssign,
|
||||
.AndAssign,
|
||||
.XorAssign,
|
||||
.OrAssign,
|
||||
=> unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
fn transCompoundStmtInline(
|
||||
rp: RestorePoint,
|
||||
parent_scope: *Scope,
|
||||
|
@ -345,9 +440,10 @@ fn transCompoundStmtInline(
|
|||
const end_it = ZigClangCompoundStmt_body_end(stmt);
|
||||
var scope = parent_scope;
|
||||
while (it != end_it) : (it += 1) {
|
||||
const result = try transStmt(rp, scope, it.*, .unused, .r_value);
|
||||
const result = try transStmt(rp, parent_scope, it.*, .unused, .r_value);
|
||||
scope = result.child_scope;
|
||||
try block_node.statements.push(result.node);
|
||||
if (result.node != &block_node.base)
|
||||
try block_node.statements.push(result.node);
|
||||
}
|
||||
return TransResult{
|
||||
.node = &block_node.base,
|
||||
|
@ -368,6 +464,427 @@ fn transCompoundStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangCompo
|
|||
};
|
||||
}
|
||||
|
||||
fn transCStyleCastExprClass(
|
||||
rp: RestorePoint,
|
||||
scope: *Scope,
|
||||
stmt: *const ZigClangCStyleCastExpr,
|
||||
result_used: ResultUsed,
|
||||
lrvalue: LRValue,
|
||||
) !TransResult {
|
||||
const sub_expr = ZigClangCStyleCastExpr_getSubExpr(stmt);
|
||||
const cast_node = (try transCCast(
|
||||
rp,
|
||||
scope,
|
||||
ZigClangCStyleCastExpr_getBeginLoc(stmt),
|
||||
ZigClangCStyleCastExpr_getType(stmt),
|
||||
ZigClangExpr_getType(sub_expr),
|
||||
(try transExpr(rp, scope, sub_expr, .used, lrvalue)).node,
|
||||
));
|
||||
const cast_res = TransResult{
|
||||
.node = cast_node,
|
||||
.child_scope = scope,
|
||||
.node_scope = scope,
|
||||
};
|
||||
return maybeSuppressResult(rp, scope, result_used, cast_res);
|
||||
}
|
||||
|
||||
fn transDeclStmt(rp: RestorePoint, parent_scope: *Scope, stmt: *const ZigClangDeclStmt) !TransResult {
|
||||
const c = rp.c;
|
||||
const block_scope = findBlockScope(parent_scope);
|
||||
var scope = parent_scope;
|
||||
|
||||
var it = ZigClangDeclStmt_decl_begin(stmt);
|
||||
const end_it = ZigClangDeclStmt_decl_end(stmt);
|
||||
while (it != end_it) : (it += 1) {
|
||||
switch (ZigClangDecl_getKind(it.*)) {
|
||||
.Var => {
|
||||
const var_decl = @ptrCast(*const ZigClangVarDecl, it.*);
|
||||
|
||||
const thread_local_token = if (ZigClangVarDecl_getTLSKind(var_decl) == .None)
|
||||
null
|
||||
else
|
||||
try appendToken(c, .Keyword_threadlocal, "threadlocal");
|
||||
const qual_type = ZigClangVarDecl_getType(var_decl);
|
||||
const mut_token = if (ZigClangQualType_isConstQualified(qual_type))
|
||||
try appendToken(c, .Keyword_const, "const")
|
||||
else
|
||||
try appendToken(c, .Keyword_var, "var");
|
||||
const c_name = try c.str(ZigClangDecl_getName_bytes_begin(
|
||||
@ptrCast(*const ZigClangDecl, var_decl),
|
||||
));
|
||||
const name_token = try appendToken(c, .Identifier, c_name);
|
||||
|
||||
const var_scope = try c.a().create(Scope.Var);
|
||||
var_scope.* = Scope.Var{
|
||||
.base = Scope{ .id = .Var, .parent = scope },
|
||||
.c_name = c_name,
|
||||
.zig_name = c_name, // TODO: getWantedName
|
||||
};
|
||||
scope = &var_scope.base;
|
||||
|
||||
const colon_token = try appendToken(c, .Colon, ":");
|
||||
const loc = ZigClangStmt_getBeginLoc(@ptrCast(*const ZigClangStmt, stmt));
|
||||
const type_node = try transQualType(rp, qual_type, loc);
|
||||
|
||||
const eq_token = try appendToken(c, .Equal, "=");
|
||||
const init_node = if (ZigClangVarDecl_getInit(var_decl)) |expr|
|
||||
(try transExpr(rp, scope, expr, .used, .r_value)).node
|
||||
else blk: {
|
||||
const undefined_token = try appendToken(c, .Keyword_undefined, "undefined");
|
||||
const undefined_node = try rp.c.a().create(ast.Node.UndefinedLiteral);
|
||||
undefined_node.* = ast.Node.UndefinedLiteral{
|
||||
.base = ast.Node{ .id = .UndefinedLiteral },
|
||||
.token = undefined_token,
|
||||
};
|
||||
break :blk &undefined_node.base;
|
||||
};
|
||||
const semicolon_token = try appendToken(c, .Semicolon, ";");
|
||||
|
||||
const node = try c.a().create(ast.Node.VarDecl);
|
||||
node.* = ast.Node.VarDecl{
|
||||
.base = ast.Node{ .id = .VarDecl },
|
||||
.doc_comments = null,
|
||||
.visib_token = null,
|
||||
.thread_local_token = thread_local_token,
|
||||
.name_token = name_token,
|
||||
.eq_token = eq_token,
|
||||
.mut_token = mut_token,
|
||||
.comptime_token = null,
|
||||
.extern_export_token = null,
|
||||
.lib_name = null,
|
||||
.type_node = type_node,
|
||||
.align_node = null, // TODO ?*Node,
|
||||
.section_node = null,
|
||||
.init_node = init_node,
|
||||
.semicolon_token = semicolon_token,
|
||||
};
|
||||
try block_scope.block_node.statements.push(&node.base);
|
||||
},
|
||||
|
||||
else => |kind| return revertAndWarn(
|
||||
rp,
|
||||
error.UnsupportedTranslation,
|
||||
ZigClangStmt_getBeginLoc(@ptrCast(*const ZigClangStmt, stmt)),
|
||||
"TODO implement translation of DeclStmt kind {}",
|
||||
@tagName(kind),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
return TransResult{
|
||||
.node = &block_scope.block_node.base,
|
||||
.node_scope = scope,
|
||||
.child_scope = scope,
|
||||
};
|
||||
}
|
||||
|
||||
fn transDeclRefExpr(
|
||||
rp: RestorePoint,
|
||||
scope: *Scope,
|
||||
expr: *const ZigClangDeclRefExpr,
|
||||
lrvalue: LRValue,
|
||||
) !TransResult {
|
||||
const value_decl = ZigClangDeclRefExpr_getDecl(expr);
|
||||
const c_name = try rp.c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, value_decl)));
|
||||
const zig_name = transLookupZigIdentifier(scope, c_name);
|
||||
if (lrvalue == .l_value) try rp.c.ptr_params.put(zig_name);
|
||||
const node = try appendIdentifier(rp.c, zig_name);
|
||||
return TransResult{
|
||||
.node = node,
|
||||
.node_scope = scope,
|
||||
.child_scope = scope,
|
||||
};
|
||||
}
|
||||
|
||||
fn transImplicitCastExpr(
|
||||
rp: RestorePoint,
|
||||
scope: *Scope,
|
||||
expr: *const ZigClangImplicitCastExpr,
|
||||
result_used: ResultUsed,
|
||||
) !TransResult {
|
||||
const c = rp.c;
|
||||
const sub_expr = ZigClangImplicitCastExpr_getSubExpr(expr);
|
||||
const sub_expr_node = try transExpr(rp, scope, @ptrCast(*const ZigClangExpr, sub_expr), .used, .r_value);
|
||||
switch (ZigClangImplicitCastExpr_getCastKind(expr)) {
|
||||
.BitCast => {
|
||||
const dest_type = getExprQualType(c, @ptrCast(*const ZigClangExpr, expr));
|
||||
const src_type = getExprQualType(c, sub_expr);
|
||||
return TransResult{
|
||||
.node = try transCCast(rp, scope, ZigClangImplicitCastExpr_getBeginLoc(expr), dest_type, src_type, sub_expr_node.node),
|
||||
.node_scope = scope,
|
||||
.child_scope = scope,
|
||||
};
|
||||
},
|
||||
.IntegralCast => {
|
||||
const dest_type = ZigClangExpr_getType(@ptrCast(*const ZigClangExpr, expr));
|
||||
const src_type = ZigClangExpr_getType(sub_expr);
|
||||
return TransResult{
|
||||
.node = try transCCast(rp, scope, ZigClangImplicitCastExpr_getBeginLoc(expr), dest_type, src_type, sub_expr_node.node),
|
||||
.node_scope = scope,
|
||||
.child_scope = scope,
|
||||
};
|
||||
},
|
||||
.FunctionToPointerDecay, .ArrayToPointerDecay => {
|
||||
return maybeSuppressResult(rp, scope, result_used, sub_expr_node);
|
||||
},
|
||||
.LValueToRValue => {
|
||||
return transExpr(rp, scope, sub_expr, .used, .r_value);
|
||||
},
|
||||
else => |kind| return revertAndWarn(
|
||||
rp,
|
||||
error.UnsupportedTranslation,
|
||||
ZigClangStmt_getBeginLoc(@ptrCast(*const ZigClangStmt, expr)),
|
||||
"TODO implement translation of CastKind {}",
|
||||
@tagName(kind),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
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 transReturnStmt(
|
||||
rp: RestorePoint,
|
||||
scope: *Scope,
|
||||
expr: *const ZigClangReturnStmt,
|
||||
) !TransResult {
|
||||
const node = try transCreateNodeReturnExpr(rp.c);
|
||||
if (ZigClangReturnStmt_getRetValue(expr)) |val_expr| {
|
||||
const ret_node = node.cast(ast.Node.ControlFlowExpression).?;
|
||||
ret_node.rhs = (try transExpr(rp, scope, val_expr, .used, .r_value)).node;
|
||||
}
|
||||
_ = try appendToken(rp.c, .Semicolon, ";");
|
||||
return TransResult{
|
||||
.node = node,
|
||||
.child_scope = scope,
|
||||
.node_scope = scope,
|
||||
};
|
||||
}
|
||||
|
||||
fn transStringLiteral(
|
||||
rp: RestorePoint,
|
||||
scope: *Scope,
|
||||
stmt: *const ZigClangStringLiteral,
|
||||
result_used: ResultUsed,
|
||||
) !TransResult {
|
||||
const kind = ZigClangStringLiteral_getKind(stmt);
|
||||
switch (kind) {
|
||||
.Ascii, .UTF8 => {
|
||||
var len: usize = undefined;
|
||||
const bytes_ptr = ZigClangStringLiteral_getString_bytes_begin_size(stmt, &len);
|
||||
const str = bytes_ptr[0..len];
|
||||
|
||||
var char_buf: [4]u8 = undefined;
|
||||
len = 0;
|
||||
for (str) |c| len += escapeChar(c, &char_buf).len;
|
||||
|
||||
const buf = try rp.c.a().alloc(u8, len + "c\"\"".len);
|
||||
buf[0] = 'c';
|
||||
buf[1] = '"';
|
||||
writeEscapedString(buf[2..], str);
|
||||
buf[buf.len - 1] = '"';
|
||||
|
||||
const token = try appendToken(rp.c, .StringLiteral, buf);
|
||||
const node = try rp.c.a().create(ast.Node.StringLiteral);
|
||||
node.* = ast.Node.StringLiteral{
|
||||
.base = ast.Node{ .id = .StringLiteral },
|
||||
.token = token,
|
||||
};
|
||||
const res = TransResult{
|
||||
.node = &node.base,
|
||||
.child_scope = scope,
|
||||
.node_scope = scope,
|
||||
};
|
||||
return maybeSuppressResult(rp, scope, result_used, res);
|
||||
},
|
||||
.UTF16, .UTF32, .Wide => return revertAndWarn(
|
||||
rp,
|
||||
error.UnsupportedTranslation,
|
||||
ZigClangStmt_getBeginLoc(@ptrCast(*const ZigClangStmt, stmt)),
|
||||
"TODO: support string literal kind {}",
|
||||
kind,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
fn escapedStringLen(s: []const u8) usize {
|
||||
var len: usize = 0;
|
||||
var char_buf: [4]u8 = undefined;
|
||||
for (s) |c| len += escapeChar(c, &char_buf).len;
|
||||
return len;
|
||||
}
|
||||
|
||||
fn writeEscapedString(buf: []u8, s: []const u8) void {
|
||||
var char_buf: [4]u8 = undefined;
|
||||
var i: usize = 0;
|
||||
for (s) |c| {
|
||||
const escaped = escapeChar(c, &char_buf);
|
||||
std.mem.copy(u8, buf[i..], escaped);
|
||||
i += escaped.len;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns either a string literal or a slice of `buf`.
|
||||
fn escapeChar(c: u8, char_buf: *[4]u8) []const u8 {
|
||||
// TODO: https://github.com/ziglang/zig/issues/2749
|
||||
const escaped = switch (c) {
|
||||
// Printable ASCII except for ' " \
|
||||
' ', '!', '#'...'&', '('...'[', ']'...'~' => ([_]u8{c})[0..],
|
||||
'\'', '\"', '\\' => ([_]u8{ '\\', c })[0..],
|
||||
'\n' => return "\\n"[0..],
|
||||
'\r' => return "\\r"[0..],
|
||||
'\t' => return "\\t"[0..],
|
||||
else => return std.fmt.bufPrint(char_buf[0..], "\\x{x:2}", c) catch unreachable,
|
||||
};
|
||||
std.mem.copy(u8, char_buf, escaped);
|
||||
return char_buf[0..escaped.len];
|
||||
}
|
||||
|
||||
fn transCCast(
|
||||
rp: RestorePoint,
|
||||
scope: *Scope,
|
||||
loc: ZigClangSourceLocation,
|
||||
dst_type: ZigClangQualType,
|
||||
src_type: ZigClangQualType,
|
||||
expr: *ast.Node,
|
||||
) !*ast.Node {
|
||||
if (ZigClangType_isVoidType(qualTypeCanon(dst_type))) return expr;
|
||||
if (ZigClangQualType_eq(dst_type, src_type)) return expr;
|
||||
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 cast_node = try transCreateNodeFnCall(rp.c, try transQualType(rp, dst_type, loc));
|
||||
const builtin_node = try transCreateNodeBuiltinFnCall(rp.c, "@ptrToInt");
|
||||
try builtin_node.params.push(expr);
|
||||
builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")");
|
||||
try cast_node.op.Call.params.push(&builtin_node.base);
|
||||
cast_node.rtoken = try appendToken(rp.c, .RParen, ")");
|
||||
return &cast_node.base;
|
||||
}
|
||||
if (cIsUnsignedInteger(src_type) and qualTypeIsPtr(dst_type)) {
|
||||
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
|
||||
// TODO: maybe bitcast to change sign
|
||||
// TODO: maybe truncate to reduce size
|
||||
const cast_node = try transCreateNodeFnCall(rp.c, try transQualType(rp, dst_type, loc));
|
||||
try cast_node.op.Call.params.push(expr);
|
||||
cast_node.rtoken = try appendToken(rp.c, .RParen, ")");
|
||||
return &cast_node.base;
|
||||
}
|
||||
|
||||
fn transExpr(
|
||||
rp: RestorePoint,
|
||||
scope: *Scope,
|
||||
expr: *const ZigClangExpr,
|
||||
used: ResultUsed,
|
||||
lrvalue: LRValue,
|
||||
) TransError!TransResult {
|
||||
return transStmt(rp, scope, @ptrCast(*const ZigClangStmt, expr), used, lrvalue);
|
||||
}
|
||||
|
||||
fn findBlockScope(inner: *Scope) *Scope.Block {
|
||||
var scope = inner;
|
||||
while (true) : (scope = scope.parent orelse unreachable) {
|
||||
if (scope.id == .Block) return @fieldParentPtr(Scope.Block, "base", scope);
|
||||
}
|
||||
}
|
||||
|
||||
fn transLookupZigIdentifier(inner: *Scope, c_name: []const u8) []const u8 {
|
||||
var scope = inner;
|
||||
while (true) : (scope = scope.parent orelse return c_name) {
|
||||
if (scope.id == .Var) {
|
||||
const var_scope = @ptrCast(*const Scope.Var, scope);
|
||||
if (std.mem.eql(u8, var_scope.c_name, c_name)) return var_scope.zig_name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn transCPtrCast(
|
||||
rp: RestorePoint,
|
||||
loc: ZigClangSourceLocation,
|
||||
dst_type: ZigClangQualType,
|
||||
src_type: ZigClangQualType,
|
||||
expr: *ast.Node,
|
||||
) !*ast.Node {
|
||||
const ty = ZigClangQualType_getTypePtr(dst_type);
|
||||
const child_type = ZigClangType_getPointeeType(ty);
|
||||
|
||||
// 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 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 aligncast_node = try transCreateNodeBuiltinFnCall(rp.c, "@alignCast");
|
||||
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);
|
||||
alignof_node.rparen_token = try appendToken(rp.c, .RParen, ")");
|
||||
try aligncast_node.params.push(&alignof_node.base);
|
||||
_ = try appendToken(rp.c, .Comma, ",");
|
||||
try aligncast_node.params.push(expr);
|
||||
aligncast_node.rparen_token = try appendToken(rp.c, .RParen, ")");
|
||||
try ptrcast_node.params.push(&aligncast_node.base);
|
||||
}
|
||||
ptrcast_node.rparen_token = try appendToken(rp.c, .RParen, ")");
|
||||
|
||||
return &ptrcast_node.base;
|
||||
}
|
||||
|
||||
fn maybeSuppressResult(
|
||||
rp: RestorePoint,
|
||||
scope: *Scope,
|
||||
used: ResultUsed,
|
||||
result: TransResult,
|
||||
) !TransResult {
|
||||
if (used == .used) return result;
|
||||
// NOTE: This is backwards, but the semicolon must immediately follow the node.
|
||||
_ = try appendToken(rp.c, .Semicolon, ";");
|
||||
const lhs = try appendIdentifier(rp.c, "_");
|
||||
const op_token = try appendToken(rp.c, .Equal, "=");
|
||||
const op_node = try rp.c.a().create(ast.Node.InfixOp);
|
||||
op_node.* = ast.Node.InfixOp{
|
||||
.base = ast.Node{ .id = .InfixOp },
|
||||
.op_token = op_token,
|
||||
.lhs = lhs,
|
||||
.op = .Assign,
|
||||
.rhs = result.node,
|
||||
};
|
||||
return TransResult{
|
||||
.node = &op_node.base,
|
||||
.child_scope = scope,
|
||||
.node_scope = scope,
|
||||
};
|
||||
}
|
||||
|
||||
fn addTopLevelDecl(c: *Context, name: []const u8, decl_node: *ast.Node) !void {
|
||||
try c.tree.root_node.decls.push(decl_node);
|
||||
}
|
||||
|
@ -376,11 +893,263 @@ fn transQualType(rp: RestorePoint, qt: ZigClangQualType, source_loc: ZigClangSou
|
|||
return transType(rp, ZigClangQualType_getTypePtr(qt), source_loc);
|
||||
}
|
||||
|
||||
fn qualTypeIsPtr(qt: ZigClangQualType) bool {
|
||||
return ZigClangType_getTypeClass(qualTypeCanon(qt)) == .Pointer;
|
||||
}
|
||||
|
||||
fn qualTypeChildIsFnProto(qt: ZigClangQualType) bool {
|
||||
const ty = ZigClangQualType_getTypePtr(qt);
|
||||
if (ZigClangType_getTypeClass(ty) == .Paren) {
|
||||
const paren_type = @ptrCast(*const ZigClangParenType, ty);
|
||||
const inner_type = ZigClangParenType_getInnerType(paren_type);
|
||||
return ZigClangQualType_getTypeClass(inner_type) == .FunctionProto;
|
||||
}
|
||||
if (ZigClangType_getTypeClass(ty) == .Attributed) {
|
||||
const attr_type = @ptrCast(*const ZigClangAttributedType, ty);
|
||||
return qualTypeChildIsFnProto(ZigClangAttributedType_getEquivalentType(attr_type));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
fn qualTypeCanon(qt: ZigClangQualType) *const ZigClangType {
|
||||
const canon = ZigClangQualType_getCanonicalType(qt);
|
||||
return ZigClangQualType_getTypePtr(canon);
|
||||
}
|
||||
|
||||
fn getExprQualType(c: *Context, expr: *const ZigClangExpr) ZigClangQualType {
|
||||
blk: {
|
||||
// If this is a C `char *`, turn it into a `const char *`
|
||||
if (ZigClangExpr_getStmtClass(expr) != .ImplicitCastExprClass) break :blk;
|
||||
const cast_expr = @ptrCast(*const ZigClangImplicitCastExpr, expr);
|
||||
if (ZigClangImplicitCastExpr_getCastKind(cast_expr) != .ArrayToPointerDecay) break :blk;
|
||||
const sub_expr = ZigClangImplicitCastExpr_getSubExpr(cast_expr);
|
||||
if (ZigClangExpr_getStmtClass(sub_expr) != .StringLiteralClass) break :blk;
|
||||
const array_qt = ZigClangExpr_getType(sub_expr);
|
||||
const array_type = @ptrCast(*const ZigClangArrayType, ZigClangQualType_getTypePtr(array_qt));
|
||||
var pointee_qt = ZigClangArrayType_getElementType(array_type);
|
||||
ZigClangQualType_addConst(&pointee_qt);
|
||||
return ZigClangASTContext_getPointerType(c.clang_context, pointee_qt);
|
||||
}
|
||||
return ZigClangExpr_getType(expr);
|
||||
}
|
||||
|
||||
fn typeIsOpaque(c: *Context, ty: *const ZigClangType, loc: ZigClangSourceLocation) bool {
|
||||
switch (ZigClangType_getTypeClass(ty)) {
|
||||
.Builtin => {
|
||||
const builtin_ty = @ptrCast(*const ZigClangBuiltinType, ty);
|
||||
return ZigClangBuiltinType_getKind(builtin_ty) == .Void;
|
||||
},
|
||||
.Record => {
|
||||
const record_ty = @ptrCast(*const ZigClangRecordType, ty);
|
||||
const record_decl = ZigClangRecordType_getDecl(record_ty);
|
||||
return (ZigClangRecordDecl_getDefinition(record_decl) == null);
|
||||
},
|
||||
.Elaborated => {
|
||||
const elaborated_ty = @ptrCast(*const ZigClangElaboratedType, ty);
|
||||
const qt = ZigClangElaboratedType_getNamedType(elaborated_ty);
|
||||
return typeIsOpaque(c, ZigClangQualType_getTypePtr(qt), loc);
|
||||
},
|
||||
.Typedef => {
|
||||
const typedef_ty = @ptrCast(*const ZigClangTypedefType, ty);
|
||||
const typedef_decl = ZigClangTypedefType_getDecl(typedef_ty);
|
||||
const underlying_type = ZigClangTypedefNameDecl_getUnderlyingType(typedef_decl);
|
||||
return typeIsOpaque(c, ZigClangQualType_getTypePtr(underlying_type), loc);
|
||||
},
|
||||
else => return false,
|
||||
}
|
||||
}
|
||||
|
||||
fn cIsUnsignedInteger(qt: ZigClangQualType) bool {
|
||||
const c_type = qualTypeCanon(qt);
|
||||
if (ZigClangType_getTypeClass(c_type) != .Builtin) return false;
|
||||
const builtin_ty = @ptrCast(*const ZigClangBuiltinType, c_type);
|
||||
return switch (ZigClangBuiltinType_getKind(builtin_ty)) {
|
||||
.Char_U,
|
||||
.UChar,
|
||||
.Char_S,
|
||||
.UShort,
|
||||
.UInt,
|
||||
.ULong,
|
||||
.ULongLong,
|
||||
.UInt128,
|
||||
.WChar_U,
|
||||
=> true,
|
||||
else => false,
|
||||
};
|
||||
}
|
||||
|
||||
fn transCreateNodeAssign(
|
||||
rp: RestorePoint,
|
||||
scope: *Scope,
|
||||
result_used: ResultUsed,
|
||||
lhs: *const ZigClangExpr,
|
||||
rhs: *const ZigClangExpr,
|
||||
) !*ast.Node.InfixOp {
|
||||
// common case
|
||||
// c: lhs = rhs
|
||||
// zig: lhs = rhs
|
||||
if (result_used == .unused) {
|
||||
const lhs_node = try transExpr(rp, scope, lhs, .used, .l_value);
|
||||
const eq_token = try appendToken(rp.c, .Equal, "=");
|
||||
const rhs_node = try transExpr(rp, scope, rhs, .used, .r_value);
|
||||
_ = try appendToken(rp.c, .Semicolon, ";");
|
||||
|
||||
const node = try rp.c.a().create(ast.Node.InfixOp);
|
||||
node.* = ast.Node.InfixOp{
|
||||
.base = ast.Node{ .id = .InfixOp },
|
||||
.op_token = eq_token,
|
||||
.lhs = lhs_node.node,
|
||||
.op = .Assign,
|
||||
.rhs = rhs_node.node,
|
||||
};
|
||||
return node;
|
||||
}
|
||||
|
||||
// worst case
|
||||
// c: lhs = rhs
|
||||
// zig: (x: {
|
||||
// zig: const _tmp = rhs;
|
||||
// zig: lhs = _tmp;
|
||||
// zig: break :x _tmp
|
||||
// zig: })
|
||||
return revertAndWarn(rp, error.UnsupportedTranslation, ZigClangExpr_getBeginLoc(lhs), "TODO: worst case assign op expr");
|
||||
}
|
||||
|
||||
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 = builtin_token,
|
||||
.params = ast.Node.BuiltinCall.ParamList.init(c.a()),
|
||||
.rparen_token = undefined, // set after appending args
|
||||
};
|
||||
return node;
|
||||
}
|
||||
|
||||
fn transCreateNodeFnCall(c: *Context, fn_expr: *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 },
|
||||
.lhs = fn_expr,
|
||||
.op = ast.Node.SuffixOp.Op{
|
||||
.Call = ast.Node.SuffixOp.Op.Call{
|
||||
.params = ast.Node.SuffixOp.Op.Call.ParamList.init(c.a()),
|
||||
.async_attr = null,
|
||||
},
|
||||
},
|
||||
.rtoken = undefined, // set after appending args
|
||||
};
|
||||
return node;
|
||||
}
|
||||
|
||||
fn transCreateNodePrefixOp(
|
||||
c: *Context,
|
||||
op: ast.Node.PrefixOp.Op,
|
||||
op_tok_id: std.zig.Token.Id,
|
||||
bytes: []const u8,
|
||||
) !*ast.Node.PrefixOp {
|
||||
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, bytes),
|
||||
.op = op,
|
||||
.rhs = undefined, // translate and set afterward
|
||||
};
|
||||
return node;
|
||||
}
|
||||
|
||||
fn transCreateNodeInfixOp(
|
||||
rp: RestorePoint,
|
||||
scope: *Scope,
|
||||
stmt: *const ZigClangBinaryOperator,
|
||||
op: ast.Node.InfixOp.Op,
|
||||
op_tok_id: std.zig.Token.Id,
|
||||
bytes: []const u8,
|
||||
grouped: bool,
|
||||
) !*ast.Node {
|
||||
const lparen = if (grouped) try appendToken(rp.c, .LParen, "(") else undefined;
|
||||
const lhs = try transExpr(rp, scope, ZigClangBinaryOperator_getLHS(stmt), .used, .l_value);
|
||||
const op_token = try appendToken(rp.c, op_tok_id, bytes);
|
||||
const rhs = try transExpr(rp, scope, ZigClangBinaryOperator_getRHS(stmt), .used, .r_value);
|
||||
const node = try rp.c.a().create(ast.Node.InfixOp);
|
||||
node.* = ast.Node.InfixOp{
|
||||
.base = ast.Node{ .id = .InfixOp },
|
||||
.op_token = op_token,
|
||||
.lhs = lhs.node,
|
||||
.op = op,
|
||||
.rhs = rhs.node,
|
||||
};
|
||||
if (!grouped) return &node.base;
|
||||
const rparen = try appendToken(rp.c, .RParen, ")");
|
||||
const grouped_expr = try rp.c.a().create(ast.Node.GroupedExpression);
|
||||
grouped_expr.* = ast.Node.GroupedExpression{
|
||||
.base = ast.Node{ .id = .GroupedExpression },
|
||||
.lparen = lparen,
|
||||
.expr = &node.base,
|
||||
.rparen = rparen,
|
||||
};
|
||||
return &grouped_expr.base;
|
||||
}
|
||||
|
||||
fn transCreateNodePtrType(
|
||||
c: *Context,
|
||||
is_const: bool,
|
||||
is_volatile: bool,
|
||||
op_tok_id: std.zig.Token.Id,
|
||||
bytes: []const u8,
|
||||
) !*ast.Node.PrefixOp {
|
||||
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, bytes),
|
||||
.op = ast.Node.PrefixOp.Op{
|
||||
.PtrType = ast.Node.PrefixOp.PtrInfo{
|
||||
.allowzero_token = null,
|
||||
.align_info = null,
|
||||
.const_token = if (is_const) try appendToken(c, .Keyword_const, "const") else null,
|
||||
.volatile_token = if (is_volatile) try appendToken(c, .Keyword_volatile, "volatile") else null,
|
||||
},
|
||||
},
|
||||
.rhs = undefined, // translate and set afterward
|
||||
};
|
||||
return node;
|
||||
}
|
||||
|
||||
fn transCreateNodeAPInt(c: *Context, int: ?*const ZigClangAPSInt) !*ast.Node {
|
||||
const num_limbs = ZigClangAPSInt_getNumWords(int.?);
|
||||
var big = try std.math.big.Int.initCapacity(c.a(), num_limbs);
|
||||
defer big.deinit();
|
||||
const data = ZigClangAPSInt_getRawData(int.?);
|
||||
var i: usize = 0;
|
||||
while (i < num_limbs) : (i += 1) big.limbs[i] = data[i];
|
||||
const str = big.toString(c.a(), 10) catch |err| switch (err) {
|
||||
error.OutOfMemory => return error.OutOfMemory,
|
||||
else => unreachable,
|
||||
};
|
||||
const token = try appendToken(c, .IntegerLiteral, str);
|
||||
const node = try c.a().create(ast.Node.IntegerLiteral);
|
||||
node.* = ast.Node.IntegerLiteral{
|
||||
.base = ast.Node{ .id = .IntegerLiteral },
|
||||
.token = token,
|
||||
};
|
||||
return &node.base;
|
||||
}
|
||||
|
||||
fn transCreateNodeReturnExpr(c: *Context) !*ast.Node {
|
||||
const ltoken = try appendToken(c, .Keyword_return, "return");
|
||||
const node = try c.a().create(ast.Node.ControlFlowExpression);
|
||||
node.* = ast.Node.ControlFlowExpression{
|
||||
.base = ast.Node{ .id = .ControlFlowExpression },
|
||||
.ltoken = ltoken,
|
||||
.kind = .Return,
|
||||
.rhs = null,
|
||||
};
|
||||
return &node.base;
|
||||
}
|
||||
|
||||
const RestorePoint = struct {
|
||||
c: *Context,
|
||||
token_index: ast.TokenIndex,
|
||||
|
@ -429,9 +1198,43 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour
|
|||
},
|
||||
.FunctionProto => {
|
||||
const fn_proto_ty = @ptrCast(*const ZigClangFunctionProtoType, ty);
|
||||
const fn_proto = try transFnProto(rp, fn_proto_ty, source_loc, null);
|
||||
const fn_proto = try transFnProto(rp, fn_proto_ty, source_loc, null, false);
|
||||
return &fn_proto.base;
|
||||
},
|
||||
.Paren => {
|
||||
const paren_ty = @ptrCast(*const ZigClangParenType, ty);
|
||||
return transQualType(rp, ZigClangParenType_getInnerType(paren_ty), source_loc);
|
||||
},
|
||||
.Pointer => {
|
||||
const child_qt = ZigClangType_getPointeeType(ty);
|
||||
if (qualTypeChildIsFnProto(child_qt)) {
|
||||
const optional_node = try transCreateNodePrefixOp(rp.c, .OptionalType, .QuestionMark, "?");
|
||||
optional_node.rhs = try transQualType(rp, child_qt, source_loc);
|
||||
return &optional_node.base;
|
||||
}
|
||||
if (typeIsOpaque(rp.c, ZigClangQualType_getTypePtr(child_qt), source_loc)) {
|
||||
const optional_node = try transCreateNodePrefixOp(rp.c, .OptionalType, .QuestionMark, "?");
|
||||
const pointer_node = try transCreateNodePtrType(
|
||||
rp.c,
|
||||
ZigClangQualType_isConstQualified(child_qt),
|
||||
ZigClangQualType_isVolatileQualified(child_qt),
|
||||
.Asterisk,
|
||||
"*",
|
||||
);
|
||||
optional_node.rhs = &pointer_node.base;
|
||||
pointer_node.rhs = try transQualType(rp, child_qt, source_loc);
|
||||
return &optional_node.base;
|
||||
}
|
||||
const pointer_node = try transCreateNodePtrType(
|
||||
rp.c,
|
||||
ZigClangQualType_isConstQualified(child_qt),
|
||||
ZigClangQualType_isVolatileQualified(child_qt),
|
||||
.BracketStarCBracket,
|
||||
"[*c]",
|
||||
);
|
||||
pointer_node.rhs = try transQualType(rp, child_qt, source_loc);
|
||||
return &pointer_node.base;
|
||||
},
|
||||
else => {
|
||||
const type_name = rp.c.str(ZigClangType_getTypeClassName(ty));
|
||||
return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported type: '{}'", type_name);
|
||||
|
@ -465,6 +1268,7 @@ fn transFnProto(
|
|||
fn_proto_ty: *const ZigClangFunctionProtoType,
|
||||
source_loc: ZigClangSourceLocation,
|
||||
fn_decl_context: ?FnDeclContext,
|
||||
is_pub: bool,
|
||||
) !*ast.Node.FnProto {
|
||||
const fn_ty = @ptrCast(*const ZigClangFunctionType, fn_proto_ty);
|
||||
const cc = try transCC(rp, fn_ty, source_loc);
|
||||
|
@ -475,7 +1279,7 @@ fn transFnProto(
|
|||
return revertAndWarn(rp, error.UnsupportedType, source_loc, "TODO: implement parameters for FunctionProto in transType");
|
||||
}
|
||||
|
||||
return finishTransFnProto(rp, fn_ty, source_loc, fn_decl_context, is_var_args, cc);
|
||||
return finishTransFnProto(rp, fn_ty, source_loc, fn_decl_context, is_var_args, cc, is_pub);
|
||||
}
|
||||
|
||||
fn transFnNoProto(
|
||||
|
@ -483,10 +1287,11 @@ fn transFnNoProto(
|
|||
fn_ty: *const ZigClangFunctionType,
|
||||
source_loc: ZigClangSourceLocation,
|
||||
fn_decl_context: ?FnDeclContext,
|
||||
is_pub: bool,
|
||||
) !*ast.Node.FnProto {
|
||||
const cc = try transCC(rp, fn_ty, source_loc);
|
||||
const is_var_args = if (fn_decl_context) |ctx| !ctx.is_export else true;
|
||||
return finishTransFnProto(rp, fn_ty, source_loc, fn_decl_context, is_var_args, cc);
|
||||
return finishTransFnProto(rp, fn_ty, source_loc, fn_decl_context, is_var_args, cc, is_pub);
|
||||
}
|
||||
|
||||
fn finishTransFnProto(
|
||||
|
@ -496,18 +1301,20 @@ fn finishTransFnProto(
|
|||
fn_decl_context: ?FnDeclContext,
|
||||
is_var_args: bool,
|
||||
cc: CallingConvention,
|
||||
is_pub: bool,
|
||||
) !*ast.Node.FnProto {
|
||||
const is_export = if (fn_decl_context) |ctx| ctx.is_export else false;
|
||||
const is_extern = if (fn_decl_context) |ctx| !ctx.has_body else true;
|
||||
|
||||
// TODO check for always_inline attribute
|
||||
// TODO check for align attribute
|
||||
|
||||
// pub extern fn name(...) T
|
||||
const pub_tok = try appendToken(rp.c, .Keyword_pub, "pub");
|
||||
const pub_tok = if (is_pub) try appendToken(rp.c, .Keyword_pub, "pub") else null;
|
||||
const cc_tok = if (cc == .Stdcall) try appendToken(rp.c, .Keyword_stdcallcc, "stdcallcc") else null;
|
||||
const extern_export_inline_tok = if (is_export)
|
||||
try appendToken(rp.c, .Keyword_export, "export")
|
||||
else if (cc == .C)
|
||||
else if (cc == .C and is_extern)
|
||||
try appendToken(rp.c, .Keyword_extern, "extern")
|
||||
else
|
||||
null;
|
||||
|
@ -657,7 +1464,7 @@ fn appendTokenFmt(c: *Context, token_id: Token.Id, comptime format: []const u8,
|
|||
.start = start_index,
|
||||
.end = end_index,
|
||||
};
|
||||
try c.source_buffer.appendByte('\n');
|
||||
try c.source_buffer.appendByte(' ');
|
||||
|
||||
return token_index;
|
||||
}
|
||||
|
|
|
@ -444,9 +444,8 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
|
|||
const char *extern_str = extern_string(node->data.fn_proto.is_extern);
|
||||
const char *export_str = export_string(node->data.fn_proto.is_export);
|
||||
const char *inline_str = inline_string(node->data.fn_proto.is_inline);
|
||||
fprintf(ar->f, "%s%s%s%sfn", pub_str, inline_str, export_str, extern_str);
|
||||
fprintf(ar->f, "%s%s%s%sfn ", pub_str, inline_str, export_str, extern_str);
|
||||
if (node->data.fn_proto.name != nullptr) {
|
||||
fprintf(ar->f, " ");
|
||||
print_symbol(ar, node->data.fn_proto.name);
|
||||
}
|
||||
fprintf(ar->f, "(");
|
||||
|
|
|
@ -3837,7 +3837,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
|
|||
return result_loc;
|
||||
} else if (handle_is_ptr(src_return_type)) {
|
||||
LLVMValueRef store_instr = LLVMBuildStore(g->builder, result, result_loc);
|
||||
LLVMSetAlignment(store_instr, LLVMGetAlignment(result_loc));
|
||||
LLVMSetAlignment(store_instr, get_ptr_align(g, instruction->result_loc->value.type));
|
||||
return result_loc;
|
||||
} else {
|
||||
return result;
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include <clang/Frontend/ASTUnit.h>
|
||||
#include <clang/Frontend/CompilerInstance.h>
|
||||
#include <clang/AST/APValue.h>
|
||||
#include <clang/AST/Expr.h>
|
||||
|
||||
#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<void *>(&src), sizeof(ZigClangExprEvalResult));
|
||||
return dest;
|
||||
}
|
||||
|
||||
static_assert(sizeof(ZigClangAPValueLValueBase) == sizeof(clang::APValue::LValueBase), "");
|
||||
static ZigClangAPValueLValueBase bitcast(clang::APValue::LValueBase src) {
|
||||
ZigClangAPValueLValueBase dest;
|
||||
|
@ -1331,6 +1353,12 @@ static ZigClangCompoundStmt_const_body_iterator bitcast(clang::CompoundStmt::con
|
|||
return dest;
|
||||
}
|
||||
|
||||
static_assert(sizeof(ZigClangDeclStmt_const_decl_iterator) == sizeof(clang::DeclStmt::const_decl_iterator), "");
|
||||
static ZigClangDeclStmt_const_decl_iterator bitcast(clang::DeclStmt::const_decl_iterator src) {
|
||||
ZigClangDeclStmt_const_decl_iterator dest;
|
||||
memcpy(&dest, static_cast<void *>(&src), sizeof(ZigClangDeclStmt_const_decl_iterator));
|
||||
return dest;
|
||||
}
|
||||
|
||||
ZigClangSourceLocation ZigClangSourceManager_getSpellingLoc(const ZigClangSourceManager *self,
|
||||
ZigClangSourceLocation Loc)
|
||||
|
@ -1381,7 +1409,7 @@ ZigClangSourceManager *ZigClangASTUnit_getSourceManager(ZigClangASTUnit *self) {
|
|||
return reinterpret_cast<ZigClangSourceManager *>(result);
|
||||
}
|
||||
|
||||
bool ZigClangASTUnit_visitLocalTopLevelDecls(ZigClangASTUnit *self, void *context,
|
||||
bool ZigClangASTUnit_visitLocalTopLevelDecls(ZigClangASTUnit *self, void *context,
|
||||
bool (*Fn)(void *context, const ZigClangDecl *decl))
|
||||
{
|
||||
return reinterpret_cast<clang::ASTUnit *>(self)->visitLocalTopLevelDecls(context,
|
||||
|
@ -1540,6 +1568,11 @@ const ZigClangType *ZigClangQualType_getTypePtr(ZigClangQualType self) {
|
|||
return reinterpret_cast<const ZigClangType *>(ty);
|
||||
}
|
||||
|
||||
ZigClangTypeClass ZigClangQualType_getTypeClass(ZigClangQualType self) {
|
||||
clang::QualType ty = bitcast(self);
|
||||
return (ZigClangTypeClass)(ty->getTypeClass());
|
||||
}
|
||||
|
||||
void ZigClangQualType_addConst(ZigClangQualType *self) {
|
||||
reinterpret_cast<clang::QualType *>(self)->addConst();
|
||||
}
|
||||
|
@ -1815,6 +1848,21 @@ void ZigClangASTUnit_delete(struct ZigClangASTUnit *self) {
|
|||
delete reinterpret_cast<clang::ASTUnit *>(self);
|
||||
}
|
||||
|
||||
struct ZigClangQualType ZigClangVarDecl_getType(const struct ZigClangVarDecl *self) {
|
||||
auto casted = reinterpret_cast<const clang::VarDecl *>(self);
|
||||
return bitcast(casted->getType());
|
||||
}
|
||||
|
||||
const struct ZigClangExpr *ZigClangVarDecl_getInit(const struct ZigClangVarDecl *self) {
|
||||
auto casted = reinterpret_cast<const clang::VarDecl *>(self);
|
||||
return reinterpret_cast<const ZigClangExpr *>(casted->getInit());
|
||||
}
|
||||
|
||||
enum ZigClangVarDecl_TLSKind ZigClangVarDecl_getTLSKind(const ZigClangVarDecl *self) {
|
||||
auto casted = reinterpret_cast<const clang::VarDecl *>(self);
|
||||
return (ZigClangVarDecl_TLSKind)casted->getTLSKind();
|
||||
}
|
||||
|
||||
enum ZigClangBuiltinTypeKind ZigClangBuiltinType_getKind(const struct ZigClangBuiltinType *self) {
|
||||
auto casted = reinterpret_cast<const clang::BuiltinType *>(self);
|
||||
return (ZigClangBuiltinTypeKind)casted->getKind();
|
||||
|
@ -1862,6 +1910,16 @@ ZigClangCompoundStmt_const_body_iterator ZigClangCompoundStmt_body_end(const str
|
|||
return bitcast(casted->body_end());
|
||||
}
|
||||
|
||||
ZigClangDeclStmt_const_decl_iterator ZigClangDeclStmt_decl_begin(const struct ZigClangDeclStmt *self) {
|
||||
auto casted = reinterpret_cast<const clang::DeclStmt *>(self);
|
||||
return bitcast(casted->decl_begin());
|
||||
}
|
||||
|
||||
ZigClangDeclStmt_const_decl_iterator ZigClangDeclStmt_decl_end(const struct ZigClangDeclStmt *self) {
|
||||
auto casted = reinterpret_cast<const clang::DeclStmt *>(self);
|
||||
return bitcast(casted->decl_end());
|
||||
}
|
||||
|
||||
unsigned ZigClangAPFloat_convertToHexString(const ZigClangAPFloat *self, char *DST,
|
||||
unsigned HexDigits, bool UpperCase, enum ZigClangAPFloat_roundingMode RM)
|
||||
{
|
||||
|
@ -1888,3 +1946,104 @@ const struct ZigClangStringLiteral *ZigClangPredefinedExpr_getFunctionName(
|
|||
const clang::StringLiteral *result = casted->getFunctionName();
|
||||
return reinterpret_cast<const struct ZigClangStringLiteral *>(result);
|
||||
}
|
||||
|
||||
ZigClangSourceLocation ZigClangImplicitCastExpr_getBeginLoc(const struct ZigClangImplicitCastExpr *self) {
|
||||
auto casted = reinterpret_cast<const clang::ImplicitCastExpr *>(self);
|
||||
return bitcast(casted->getBeginLoc());
|
||||
}
|
||||
|
||||
enum ZigClangCK ZigClangImplicitCastExpr_getCastKind(const struct ZigClangImplicitCastExpr *self) {
|
||||
auto casted = reinterpret_cast<const clang::ImplicitCastExpr *>(self);
|
||||
return (ZigClangCK)casted->getCastKind();
|
||||
}
|
||||
|
||||
const struct ZigClangExpr *ZigClangImplicitCastExpr_getSubExpr(const struct ZigClangImplicitCastExpr *self) {
|
||||
auto casted = reinterpret_cast<const clang::ImplicitCastExpr *>(self);
|
||||
return reinterpret_cast<const struct ZigClangExpr *>(casted->getSubExpr());
|
||||
}
|
||||
|
||||
struct ZigClangQualType ZigClangArrayType_getElementType(const struct ZigClangArrayType *self) {
|
||||
auto casted = reinterpret_cast<const clang::ArrayType *>(self);
|
||||
return bitcast(casted->getElementType());
|
||||
}
|
||||
|
||||
const struct ZigClangValueDecl *ZigClangDeclRefExpr_getDecl(const struct ZigClangDeclRefExpr *self) {
|
||||
auto casted = reinterpret_cast<const clang::DeclRefExpr *>(self);
|
||||
return reinterpret_cast<const struct ZigClangValueDecl *>(casted->getDecl());
|
||||
}
|
||||
|
||||
struct ZigClangQualType ZigClangParenType_getInnerType(const struct ZigClangParenType *self) {
|
||||
auto casted = reinterpret_cast<const clang::ParenType *>(self);
|
||||
return bitcast(casted->getInnerType());
|
||||
}
|
||||
|
||||
struct ZigClangQualType ZigClangAttributedType_getEquivalentType(const struct ZigClangAttributedType *self) {
|
||||
auto casted = reinterpret_cast<const clang::AttributedType *>(self);
|
||||
return bitcast(casted->getEquivalentType());
|
||||
}
|
||||
|
||||
struct ZigClangQualType ZigClangElaboratedType_getNamedType(const struct ZigClangElaboratedType *self) {
|
||||
auto casted = reinterpret_cast<const clang::ElaboratedType *>(self);
|
||||
return bitcast(casted->getNamedType());
|
||||
}
|
||||
|
||||
struct ZigClangSourceLocation ZigClangCStyleCastExpr_getBeginLoc(const struct ZigClangCStyleCastExpr *self) {
|
||||
auto casted = reinterpret_cast<const clang::CStyleCastExpr *>(self);
|
||||
return bitcast(casted->getBeginLoc());
|
||||
}
|
||||
|
||||
const struct ZigClangExpr *ZigClangCStyleCastExpr_getSubExpr(const struct ZigClangCStyleCastExpr *self) {
|
||||
auto casted = reinterpret_cast<const clang::CStyleCastExpr *>(self);
|
||||
return reinterpret_cast<const struct ZigClangExpr *>(casted->getSubExpr());
|
||||
}
|
||||
|
||||
struct ZigClangQualType ZigClangCStyleCastExpr_getType(const struct ZigClangCStyleCastExpr *self) {
|
||||
auto casted = reinterpret_cast<const clang::CStyleCastExpr *>(self);
|
||||
return bitcast(casted->getType());
|
||||
}
|
||||
|
||||
bool ZigClangIntegerLiteral_EvaluateAsInt(const struct ZigClangIntegerLiteral *self, struct ZigClangExprEvalResult *result, const struct ZigClangASTContext *ctx) {
|
||||
auto casted_self = reinterpret_cast<const clang::IntegerLiteral *>(self);
|
||||
auto casted_ctx = reinterpret_cast<const clang::ASTContext *>(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<const clang::IntegerLiteral *>(self);
|
||||
return bitcast(casted->getBeginLoc());
|
||||
}
|
||||
|
||||
const struct ZigClangExpr *ZigClangReturnStmt_getRetValue(const struct ZigClangReturnStmt *self) {
|
||||
auto casted = reinterpret_cast<const clang::ReturnStmt *>(self);
|
||||
return reinterpret_cast<const struct ZigClangExpr *>(casted->getRetValue());
|
||||
}
|
||||
|
||||
enum ZigClangBO ZigClangBinaryOperator_getOpcode(const struct ZigClangBinaryOperator *self) {
|
||||
auto casted = reinterpret_cast<const clang::BinaryOperator *>(self);
|
||||
return (ZigClangBO)casted->getOpcode();
|
||||
}
|
||||
|
||||
struct ZigClangSourceLocation ZigClangBinaryOperator_getBeginLoc(const struct ZigClangBinaryOperator *self) {
|
||||
auto casted = reinterpret_cast<const clang::BinaryOperator *>(self);
|
||||
return bitcast(casted->getBeginLoc());
|
||||
}
|
||||
|
||||
const struct ZigClangExpr *ZigClangBinaryOperator_getLHS(const struct ZigClangBinaryOperator *self) {
|
||||
auto casted = reinterpret_cast<const clang::BinaryOperator *>(self);
|
||||
return reinterpret_cast<const struct ZigClangExpr *>(casted->getLHS());
|
||||
}
|
||||
|
||||
const struct ZigClangExpr *ZigClangBinaryOperator_getRHS(const struct ZigClangBinaryOperator *self) {
|
||||
auto casted = reinterpret_cast<const clang::BinaryOperator *>(self);
|
||||
return reinterpret_cast<const struct ZigClangExpr *>(casted->getRHS());
|
||||
}
|
||||
|
||||
struct ZigClangQualType ZigClangBinaryOperator_getType(const struct ZigClangBinaryOperator *self) {
|
||||
auto casted = reinterpret_cast<const clang::BinaryOperator *>(self);
|
||||
return bitcast(casted->getType());
|
||||
}
|
||||
|
|
|
@ -30,6 +30,38 @@ 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;
|
||||
// experimentally-derived size of clang::APValue::DataType
|
||||
#ifdef _WIN32
|
||||
char Data[52];
|
||||
#else
|
||||
char Data[68];
|
||||
#endif
|
||||
};
|
||||
|
||||
struct ZigClangExprEvalResult {
|
||||
bool HasSideEffects;
|
||||
bool HasUndefinedBehavior;
|
||||
void *SmallVectorImpl;
|
||||
ZigClangAPValue Val;
|
||||
};
|
||||
|
||||
struct ZigClangAPValue;
|
||||
struct ZigClangAPSInt;
|
||||
struct ZigClangAPFloat;
|
||||
|
@ -105,6 +137,7 @@ struct ZigClangFunctionType;
|
|||
struct ZigClangPredefinedExpr;
|
||||
|
||||
typedef struct ZigClangStmt *const * ZigClangCompoundStmt_const_body_iterator;
|
||||
typedef struct ZigClangDecl *const * ZigClangDeclStmt_const_decl_iterator;
|
||||
|
||||
enum ZigClangBO {
|
||||
ZigClangBO_PtrMemD,
|
||||
|
@ -732,6 +765,12 @@ enum ZigClangStringLiteral_StringKind {
|
|||
ZigClangStringLiteral_StringKind_UTF32,
|
||||
};
|
||||
|
||||
enum ZigClangVarDecl_TLSKind {
|
||||
ZigClangVarDecl_TLSKind_None,
|
||||
ZigClangVarDecl_TLSKind_Static,
|
||||
ZigClangVarDecl_TLSKind_Dynamic,
|
||||
};
|
||||
|
||||
ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangSourceManager_getSpellingLoc(const struct ZigClangSourceManager *,
|
||||
struct ZigClangSourceLocation Loc);
|
||||
ZIG_EXTERN_C const char *ZigClangSourceManager_getFilename(const struct ZigClangSourceManager *,
|
||||
|
@ -754,7 +793,7 @@ ZIG_EXTERN_C void ZigClangErrorMsg_delete(struct Stage2ErrorMsg *ptr, size_t len
|
|||
|
||||
ZIG_EXTERN_C struct ZigClangASTContext *ZigClangASTUnit_getASTContext(struct ZigClangASTUnit *);
|
||||
ZIG_EXTERN_C struct ZigClangSourceManager *ZigClangASTUnit_getSourceManager(struct ZigClangASTUnit *);
|
||||
ZIG_EXTERN_C bool ZigClangASTUnit_visitLocalTopLevelDecls(struct ZigClangASTUnit *, void *context,
|
||||
ZIG_EXTERN_C bool ZigClangASTUnit_visitLocalTopLevelDecls(struct ZigClangASTUnit *, void *context,
|
||||
bool (*Fn)(void *context, const struct ZigClangDecl *decl));
|
||||
|
||||
ZIG_EXTERN_C const struct ZigClangRecordDecl *ZigClangRecordType_getDecl(const struct ZigClangRecordType *record_ty);
|
||||
|
@ -789,6 +828,10 @@ ZIG_EXTERN_C const char *ZigClangDecl_getName_bytes_begin(const struct ZigClangD
|
|||
ZIG_EXTERN_C enum ZigClangDeclKind ZigClangDecl_getKind(const struct ZigClangDecl *decl);
|
||||
ZIG_EXTERN_C const char *ZigClangDecl_getDeclKindName(const struct ZigClangDecl *decl);
|
||||
|
||||
ZIG_EXTERN_C struct ZigClangQualType ZigClangVarDecl_getType(const struct ZigClangVarDecl *);
|
||||
ZIG_EXTERN_C const struct ZigClangExpr *ZigClangVarDecl_getInit(const struct ZigClangVarDecl *var_decl);
|
||||
ZIG_EXTERN_C enum ZigClangVarDecl_TLSKind ZigClangVarDecl_getTLSKind(const struct ZigClangVarDecl *var_decl);
|
||||
|
||||
ZIG_EXTERN_C bool ZigClangSourceLocation_eq(struct ZigClangSourceLocation a, struct ZigClangSourceLocation b);
|
||||
|
||||
ZIG_EXTERN_C const struct ZigClangTypedefNameDecl *ZigClangTypedefType_getDecl(const struct ZigClangTypedefType *);
|
||||
|
@ -796,6 +839,7 @@ ZIG_EXTERN_C struct ZigClangQualType ZigClangTypedefNameDecl_getUnderlyingType(c
|
|||
|
||||
ZIG_EXTERN_C struct ZigClangQualType ZigClangQualType_getCanonicalType(struct ZigClangQualType);
|
||||
ZIG_EXTERN_C const struct ZigClangType *ZigClangQualType_getTypePtr(struct ZigClangQualType);
|
||||
ZIG_EXTERN_C enum ZigClangTypeClass ZigClangQualType_getTypeClass(struct ZigClangQualType);
|
||||
ZIG_EXTERN_C void ZigClangQualType_addConst(struct ZigClangQualType *);
|
||||
ZIG_EXTERN_C bool ZigClangQualType_eq(struct ZigClangQualType, struct ZigClangQualType);
|
||||
ZIG_EXTERN_C bool ZigClangQualType_isConstQualified(struct ZigClangQualType);
|
||||
|
@ -846,6 +890,9 @@ ZIG_EXTERN_C struct ZigClangQualType ZigClangFunctionProtoType_getParamType(cons
|
|||
ZIG_EXTERN_C ZigClangCompoundStmt_const_body_iterator ZigClangCompoundStmt_body_begin(const struct ZigClangCompoundStmt *self);
|
||||
ZIG_EXTERN_C ZigClangCompoundStmt_const_body_iterator ZigClangCompoundStmt_body_end(const struct ZigClangCompoundStmt *self);
|
||||
|
||||
ZIG_EXTERN_C ZigClangDeclStmt_const_decl_iterator ZigClangDeclStmt_decl_begin(const struct ZigClangDeclStmt *self);
|
||||
ZIG_EXTERN_C ZigClangDeclStmt_const_decl_iterator ZigClangDeclStmt_decl_end(const struct ZigClangDeclStmt *self);
|
||||
|
||||
ZIG_EXTERN_C unsigned ZigClangAPFloat_convertToHexString(const struct ZigClangAPFloat *self, char *DST,
|
||||
unsigned HexDigits, bool UpperCase, enum ZigClangAPFloat_roundingMode RM);
|
||||
|
||||
|
@ -855,4 +902,34 @@ ZIG_EXTERN_C const char *ZigClangStringLiteral_getString_bytes_begin_size(const
|
|||
|
||||
ZIG_EXTERN_C const struct ZigClangStringLiteral *ZigClangPredefinedExpr_getFunctionName(
|
||||
const struct ZigClangPredefinedExpr *self);
|
||||
|
||||
ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangImplicitCastExpr_getBeginLoc(const struct ZigClangImplicitCastExpr *);
|
||||
ZIG_EXTERN_C enum ZigClangCK ZigClangImplicitCastExpr_getCastKind(const struct ZigClangImplicitCastExpr *);
|
||||
ZIG_EXTERN_C const struct ZigClangExpr *ZigClangImplicitCastExpr_getSubExpr(const struct ZigClangImplicitCastExpr *);
|
||||
|
||||
ZIG_EXTERN_C struct ZigClangQualType ZigClangArrayType_getElementType(const struct ZigClangArrayType *);
|
||||
|
||||
ZIG_EXTERN_C const struct ZigClangValueDecl *ZigClangDeclRefExpr_getDecl(const struct ZigClangDeclRefExpr *);
|
||||
|
||||
ZIG_EXTERN_C struct ZigClangQualType ZigClangParenType_getInnerType(const struct ZigClangParenType *);
|
||||
|
||||
ZIG_EXTERN_C struct ZigClangQualType ZigClangAttributedType_getEquivalentType(const struct ZigClangAttributedType *);
|
||||
|
||||
ZIG_EXTERN_C struct ZigClangQualType ZigClangElaboratedType_getNamedType(const struct ZigClangElaboratedType *);
|
||||
|
||||
ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangCStyleCastExpr_getBeginLoc(const struct ZigClangCStyleCastExpr *);
|
||||
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 *);
|
||||
|
||||
ZIG_EXTERN_C const struct ZigClangExpr *ZigClangReturnStmt_getRetValue(const struct ZigClangReturnStmt *);
|
||||
|
||||
ZIG_EXTERN_C enum ZigClangBO ZigClangBinaryOperator_getOpcode(const struct ZigClangBinaryOperator *);
|
||||
ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangBinaryOperator_getBeginLoc(const struct ZigClangBinaryOperator *);
|
||||
ZIG_EXTERN_C const struct ZigClangExpr *ZigClangBinaryOperator_getLHS(const struct ZigClangBinaryOperator *);
|
||||
ZIG_EXTERN_C const struct ZigClangExpr *ZigClangBinaryOperator_getRHS(const struct ZigClangBinaryOperator *);
|
||||
ZIG_EXTERN_C struct ZigClangQualType ZigClangBinaryOperator_getType(const struct ZigClangBinaryOperator *);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -18,28 +18,80 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
|||
\\pub extern fn bar() c_int;
|
||||
);
|
||||
|
||||
cases.add_both("simple var decls",
|
||||
\\void foo(void) {
|
||||
\\ int a;
|
||||
\\ char b = 123;
|
||||
\\ const int c;
|
||||
\\ const unsigned d = 440;
|
||||
\\}
|
||||
,
|
||||
\\pub fn foo() void {
|
||||
\\ var a: c_int = undefined;
|
||||
\\ var b: u8 = u8(123);
|
||||
\\ const c: c_int = undefined;
|
||||
\\ const d: c_uint = c_uint(440);
|
||||
\\}
|
||||
);
|
||||
|
||||
cases.add_both("ignore result, explicit function arguments",
|
||||
\\void foo(void) {
|
||||
\\ int a;
|
||||
\\ 1;
|
||||
\\ "hey";
|
||||
\\ 1 + 1;
|
||||
\\ 1 - 1;
|
||||
\\ a = 1;
|
||||
\\}
|
||||
,
|
||||
\\pub fn foo() void {
|
||||
\\ var a: c_int = undefined;
|
||||
\\ _ = 1;
|
||||
\\ _ = c"hey";
|
||||
\\ _ = (1 + 1);
|
||||
\\ _ = (1 - 1);
|
||||
\\ a = 1;
|
||||
\\}
|
||||
);
|
||||
|
||||
/////////////// Cases that pass for only stage2 ////////////////
|
||||
cases.add_2("Parameterless function prototypes",
|
||||
// TODO: restore these tests after removing "import mode" concept
|
||||
// https://github.com/ziglang/zig/issues/2780
|
||||
|
||||
// cases.add_2("Parameterless function prototypes",
|
||||
// \\void a() {}
|
||||
// \\void b(void) {}
|
||||
// \\void c();
|
||||
// \\void d(void);
|
||||
// ,
|
||||
// \\pub export fn a() void {}
|
||||
// \\pub export fn b() void {}
|
||||
// \\pub extern fn c(...) void;
|
||||
// \\pub extern fn d() void;
|
||||
// );
|
||||
|
||||
// cases.add_2("simple function definition",
|
||||
// \\void foo(void) {}
|
||||
// \\static void bar(void) {}
|
||||
// ,
|
||||
// \\pub export fn foo() void {}
|
||||
// \\pub extern fn bar() void {}
|
||||
// );
|
||||
|
||||
cases.add_2("parameterless function prototypes",
|
||||
\\void a() {}
|
||||
\\void b(void) {}
|
||||
\\void c();
|
||||
\\void d(void);
|
||||
,
|
||||
\\pub export fn a() void {}
|
||||
\\pub export fn b() void {}
|
||||
\\pub fn a(...) void {}
|
||||
\\pub fn b() void {}
|
||||
\\pub extern fn c(...) void;
|
||||
\\pub extern fn d() void;
|
||||
);
|
||||
|
||||
cases.add_2("simple function definition",
|
||||
\\void foo(void) {}
|
||||
\\static void bar(void) {}
|
||||
,
|
||||
\\pub export fn foo() void {}
|
||||
\\pub extern fn bar() void {}
|
||||
);
|
||||
|
||||
/////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
|
||||
|
||||
cases.add("typedef of function in struct field",
|
||||
\\typedef void lws_callback_function(void);
|
||||
\\struct Foo {
|
||||
|
@ -47,9 +99,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
|||
\\ lws_callback_function *callback_http;
|
||||
\\};
|
||||
,
|
||||
\\pub const lws_callback_function = extern fn() void;
|
||||
\\pub const lws_callback_function = extern fn () void;
|
||||
\\pub const struct_Foo = extern struct {
|
||||
\\ func: ?extern fn() void,
|
||||
\\ func: ?extern fn () void,
|
||||
\\ callback_http: ?lws_callback_function,
|
||||
\\};
|
||||
);
|
||||
|
@ -68,13 +120,21 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
|||
\\};
|
||||
);
|
||||
|
||||
cases.add_both("simple function definition",
|
||||
\\void foo(void) {}
|
||||
\\static void bar(void) {}
|
||||
,
|
||||
\\pub fn foo() void {}
|
||||
\\pub fn bar() void {}
|
||||
);
|
||||
|
||||
cases.add("macro with left shift",
|
||||
\\#define REDISMODULE_READ (1<<0)
|
||||
,
|
||||
\\pub const REDISMODULE_READ = 1 << 0;
|
||||
);
|
||||
|
||||
cases.add("casting pointers to ints and ints to pointers",
|
||||
cases.add_both("casting pointers to ints and ints to pointers",
|
||||
\\void foo(void);
|
||||
\\void bar(void) {
|
||||
\\ void *func_ptr = foo;
|
||||
|
@ -84,7 +144,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
|||
\\pub extern fn foo() void;
|
||||
\\pub fn bar() void {
|
||||
\\ var func_ptr: ?*c_void = @ptrCast(?*c_void, foo);
|
||||
\\ var typed_func_ptr: ?extern fn() void = @intToPtr(?extern fn() void, c_ulong(@ptrToInt(func_ptr)));
|
||||
\\ var typed_func_ptr: ?extern fn () void = @intToPtr(?extern fn () void, c_ulong(@ptrToInt(func_ptr)));
|
||||
\\}
|
||||
);
|
||||
|
||||
|
@ -159,7 +219,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
|||
\\}
|
||||
);
|
||||
|
||||
cases.add("ignore result",
|
||||
cases.add("ignore result, no function arguments",
|
||||
\\void foo() {
|
||||
\\ int a;
|
||||
\\ 1;
|
||||
|
@ -260,7 +320,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
|||
\\pub extern fn baz(a: i8, b: i16, c: i32, d: i64) void;
|
||||
);
|
||||
|
||||
cases.add("noreturn attribute",
|
||||
cases.add_both("noreturn attribute",
|
||||
\\void foo(void) __attribute__((noreturn));
|
||||
,
|
||||
\\pub extern fn foo() noreturn;
|
||||
|
@ -384,7 +444,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
|||
\\};
|
||||
,
|
||||
\\pub const struct_Foo = extern struct {
|
||||
\\ derp: ?extern fn([*c]struct_Foo) void,
|
||||
\\ derp: ?extern fn ([*c]struct_Foo) void,
|
||||
\\};
|
||||
,
|
||||
\\pub const Foo = struct_Foo;
|
||||
|
@ -467,13 +527,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
|||
\\extern char (*fn_ptr2)(int, float);
|
||||
\\#define bar fn_ptr2
|
||||
,
|
||||
\\pub extern var fn_ptr: ?extern fn() void;
|
||||
\\pub extern var fn_ptr: ?extern fn () void;
|
||||
,
|
||||
\\pub inline fn foo() void {
|
||||
\\ return fn_ptr.?();
|
||||
\\}
|
||||
,
|
||||
\\pub extern var fn_ptr2: ?extern fn(c_int, f32) u8;
|
||||
\\pub extern var fn_ptr2: ?extern fn (c_int, f32) u8;
|
||||
,
|
||||
\\pub inline fn bar(arg0: c_int, arg1: f32) u8 {
|
||||
\\ return fn_ptr2.?(arg0, arg1);
|
||||
|
@ -489,7 +549,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
|||
cases.add("__cdecl doesn't mess up function pointers",
|
||||
\\void foo(void (__cdecl *fn_ptr)(void));
|
||||
,
|
||||
\\pub extern fn foo(fn_ptr: ?extern fn() void) void;
|
||||
\\pub extern fn foo(fn_ptr: ?extern fn () void) void;
|
||||
);
|
||||
|
||||
cases.add("comment after integer literal",
|
||||
|
@ -1236,8 +1296,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
|||
\\ return 0;
|
||||
\\}
|
||||
\\pub export fn bar() void {
|
||||
\\ var f: ?extern fn() void = foo;
|
||||
\\ var b: ?extern fn() c_int = baz;
|
||||
\\ var f: ?extern fn () void = foo;
|
||||
\\ var b: ?extern fn () c_int = baz;
|
||||
\\ f.?();
|
||||
\\ f.?();
|
||||
\\ foo();
|
||||
|
@ -1372,9 +1432,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
|||
,
|
||||
\\pub const GLbitfield = c_uint;
|
||||
,
|
||||
\\pub const PFNGLCLEARPROC = ?extern fn(GLbitfield) void;
|
||||
\\pub const PFNGLCLEARPROC = ?extern fn (GLbitfield) void;
|
||||
,
|
||||
\\pub const OpenGLProc = ?extern fn() void;
|
||||
\\pub const OpenGLProc = ?extern fn () void;
|
||||
,
|
||||
\\pub const union_OpenGLProcs = extern union {
|
||||
\\ ptr: [1]OpenGLProc,
|
||||
|
|
Loading…
Reference in New Issue