| ... | @@ -31,6 +31,12 @@ fn addrEql(a: usize, b: usize) bool { | ... | @@ -31,6 +31,12 @@ fn addrEql(a: usize, b: usize) bool { |
| 31 | return a == b; | 31 | return a == b; |
| 32 | } | 32 | } |
| 33 | | 33 | |
| | 34 | const SymbolTable = std.StringHashMap(void); |
| | 35 | const AliasList = std.SegmentedList(struct { |
| | 36 | alias: []const u8, |
| | 37 | name: []const u8, |
| | 38 | }, 4); |
| | 39 | |
| 34 | const Scope = struct { | 40 | const Scope = struct { |
| 35 | id: Id, | 41 | id: Id, |
| 36 | parent: ?*Scope, | 42 | parent: ?*Scope, |
| ... | @@ -98,6 +104,8 @@ const Context = struct { | ... | @@ -98,6 +104,8 @@ const Context = struct { |
| 98 | err: Error, | 104 | err: Error, |
| 99 | source_manager: *ZigClangSourceManager, | 105 | source_manager: *ZigClangSourceManager, |
| 100 | decl_table: DeclTable, | 106 | decl_table: DeclTable, |
| | 107 | alias_list: AliasList, |
| | 108 | sym_table: SymbolTable, |
| 101 | global_scope: *Scope.Root, | 109 | global_scope: *Scope.Root, |
| 102 | ptr_params: std.BufSet, | 110 | ptr_params: std.BufSet, |
| 103 | clang_context: *ZigClangASTContext, | 111 | clang_context: *ZigClangASTContext, |
| ... | @@ -177,6 +185,8 @@ pub fn translate( | ... | @@ -177,6 +185,8 @@ pub fn translate( |
| 177 | .source_manager = ZigClangASTUnit_getSourceManager(ast_unit), | 185 | .source_manager = ZigClangASTUnit_getSourceManager(ast_unit), |
| 178 | .err = undefined, | 186 | .err = undefined, |
| 179 | .decl_table = DeclTable.init(arena), | 187 | .decl_table = DeclTable.init(arena), |
| | 188 | .alias_list = AliasList.init(arena), |
| | 189 | .sym_table = SymbolTable.init(arena), |
| 180 | .global_scope = try arena.create(Scope.Root), | 190 | .global_scope = try arena.create(Scope.Root), |
| 181 | .ptr_params = std.BufSet.init(arena), | 191 | .ptr_params = std.BufSet.init(arena), |
| 182 | .clang_context = ZigClangASTUnit_getASTContext(ast_unit).?, | 192 | .clang_context = ZigClangASTUnit_getASTContext(ast_unit).?, |
| ... | @@ -191,6 +201,12 @@ pub fn translate( | ... | @@ -191,6 +201,12 @@ pub fn translate( |
| 191 | if (!ZigClangASTUnit_visitLocalTopLevelDecls(ast_unit, &context, declVisitorC)) { | 201 | if (!ZigClangASTUnit_visitLocalTopLevelDecls(ast_unit, &context, declVisitorC)) { |
| 192 | return context.err; | 202 | return context.err; |
| 193 | } | 203 | } |
| | 204 | var it = context.alias_list.iterator(0); |
| | 205 | while (it.next()) |alias| { |
| | 206 | if (!context.sym_table.contains(alias.alias)) { |
| | 207 | try createAlias(&context, alias); |
| | 208 | } |
| | 209 | } |
| 194 | | 210 | |
| 195 | tree.root_node.eof_token = try appendToken(&context, .Eof, ""); | 211 | tree.root_node.eof_token = try appendToken(&context, .Eof, ""); |
| 196 | tree.source = source_buffer.toOwnedSlice(); | 212 | tree.source = source_buffer.toOwnedSlice(); |
| ... | @@ -220,13 +236,13 @@ fn declVisitor(c: *Context, decl: *const ZigClangDecl) Error!void { | ... | @@ -220,13 +236,13 @@ fn declVisitor(c: *Context, decl: *const ZigClangDecl) Error!void { |
| 220 | return visitFnDecl(c, @ptrCast(*const ZigClangFunctionDecl, decl)); | 236 | return visitFnDecl(c, @ptrCast(*const ZigClangFunctionDecl, decl)); |
| 221 | }, | 237 | }, |
| 222 | .Typedef => { | 238 | .Typedef => { |
| 223 | try resolveTypeDef(c, @ptrCast(*const ZigClangTypedefNameDecl, decl)); | 239 | return resolveTypeDef(c, @ptrCast(*const ZigClangTypedefNameDecl, decl)); |
| 224 | }, | 240 | }, |
| 225 | .Enum => { | 241 | .Enum => { |
| 226 | try emitWarning(c, ZigClangDecl_getLocation(decl), "TODO implement translate-c for enums", .{}); | 242 | try emitWarning(c, ZigClangDecl_getLocation(decl), "TODO implement translate-c for enums", .{}); |
| 227 | }, | 243 | }, |
| 228 | .Record => { | 244 | .Record => { |
| 229 | try emitWarning(c, ZigClangDecl_getLocation(decl), "TODO implement translate-c for structs", .{}); | 245 | return resolveRecordDecl(c, @ptrCast(*const ZigClangRecordDecl, decl)); |
| 230 | }, | 246 | }, |
| 231 | .Var => { | 247 | .Var => { |
| 232 | return visitVarDecl(c, @ptrCast(*const ZigClangVarDecl, decl)); | 248 | return visitVarDecl(c, @ptrCast(*const ZigClangVarDecl, decl)); |
| ... | @@ -398,9 +414,7 @@ fn resolveTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl) Err | ... | @@ -398,9 +414,7 @@ fn resolveTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl) Err |
| 398 | const typedef_loc = ZigClangTypedefNameDecl_getLocation(typedef_decl); | 414 | const typedef_loc = ZigClangTypedefNameDecl_getLocation(typedef_decl); |
| 399 | const type_node = transQualType(rp, child_qt, typedef_loc) catch |err| switch (err) { | 415 | const type_node = transQualType(rp, child_qt, typedef_loc) catch |err| switch (err) { |
| 400 | error.UnsupportedType => { | 416 | error.UnsupportedType => { |
| 401 | const node = try failDecl(c, typedef_loc, typedef_name, "unable to resolve typedef child type", .{}); | 417 | return failDecl(c, typedef_loc, typedef_name, "unable to resolve typedef child type", .{}); |
| 402 | _ = try c.decl_table.put(@ptrToInt(typedef_decl), node); | | |
| 403 | return node; | | |
| 404 | }, | 418 | }, |
| 405 | error.OutOfMemory => |e| return e, | 419 | error.OutOfMemory => |e| return e, |
| 406 | }; | 420 | }; |
| ... | @@ -426,6 +440,89 @@ fn resolveTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl) Err | ... | @@ -426,6 +440,89 @@ fn resolveTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl) Err |
| 426 | try addTopLevelDecl(c, typedef_name, &node.base); | 440 | try addTopLevelDecl(c, typedef_name, &node.base); |
| 427 | } | 441 | } |
| 428 | | 442 | |
| | 443 | fn resolveRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!void { |
| | 444 | if (try c.decl_table.put(@ptrToInt(ZigClangRecordDecl_getCanonicalDecl(record_decl)), {})) |_| return; // Avoid processing this decl twice |
| | 445 | const rp = makeRestorePoint(c); |
| | 446 | |
| | 447 | const bare_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, record_decl))); |
| | 448 | |
| | 449 | const container_kind_name = if (ZigClangRecordDecl_isUnion(record_decl)) |
| | 450 | "union" |
| | 451 | else if (ZigClangRecordDecl_isStruct(record_decl)) |
| | 452 | "struct" |
| | 453 | else |
| | 454 | return failDecl(c, ZigClangRecordDecl_getLocation(record_decl), bare_name, "record {} is not a struct or union", .{bare_name}); |
| | 455 | |
| | 456 | if (ZigClangRecordDecl_isAnonymousStructOrUnion(record_decl) or bare_name.len == 0) |
| | 457 | return; |
| | 458 | |
| | 459 | const visib_tok = try appendToken(c, .Keyword_pub, "pub"); |
| | 460 | const const_tok = try appendToken(c, .Keyword_const, "const"); |
| | 461 | |
| | 462 | const name = try std.fmt.allocPrint(c.a(), "{}_{}", .{ container_kind_name, bare_name }); |
| | 463 | const name_tok = try appendToken(c, .Identifier, name); |
| | 464 | |
| | 465 | const eq_tok = try appendToken(c, .Equal, "="); |
| | 466 | const init_node = transRecordDecl(c, record_decl) catch |err| switch (err) { |
| | 467 | error.UnsupportedType => { |
| | 468 | return failDecl(c, ZigClangRecordDecl_getLocation(record_decl), name, "unable to resolve record type", .{}); |
| | 469 | }, |
| | 470 | error.OutOfMemory => |e| return e, |
| | 471 | }; |
| | 472 | const semicolon_token = try appendToken(c, .Semicolon, ";"); |
| | 473 | |
| | 474 | const node = try c.a().create(ast.Node.VarDecl); |
| | 475 | node.* = ast.Node.VarDecl{ |
| | 476 | .base = ast.Node{ .id = .VarDecl }, |
| | 477 | .doc_comments = null, |
| | 478 | .visib_token = visib_tok, |
| | 479 | .thread_local_token = null, |
| | 480 | .name_token = name_tok, |
| | 481 | .eq_token = eq_tok, |
| | 482 | .mut_token = const_tok, |
| | 483 | .comptime_token = null, |
| | 484 | .extern_export_token = null, |
| | 485 | .lib_name = null, |
| | 486 | .type_node = null, |
| | 487 | .align_node = null, |
| | 488 | .section_node = null, |
| | 489 | .init_node = init_node, |
| | 490 | .semicolon_token = semicolon_token, |
| | 491 | }; |
| | 492 | |
| | 493 | try addTopLevelDecl(c, name, &node.base); |
| | 494 | try c.alias_list.push(.{ .alias = bare_name, .name = name }); |
| | 495 | } |
| | 496 | |
| | 497 | fn createAlias(c: *Context, alias: var) !void { |
| | 498 | const visib_tok = try appendToken(c, .Keyword_pub, "pub"); |
| | 499 | const mut_tok = try appendToken(c, .Keyword_const, "const"); |
| | 500 | const name_tok = try appendToken(c, .Identifier, alias.alias); |
| | 501 | |
| | 502 | const eq_tok = try appendToken(c, .Equal, "="); |
| | 503 | const init_node = try appendIdentifier(c, alias.name); |
| | 504 | |
| | 505 | const node = try c.a().create(ast.Node.VarDecl); |
| | 506 | node.* = ast.Node.VarDecl{ |
| | 507 | .base = ast.Node{ .id = .VarDecl }, |
| | 508 | .doc_comments = null, |
| | 509 | .visib_token = visib_tok, |
| | 510 | .thread_local_token = null, |
| | 511 | .name_token = name_tok, |
| | 512 | .eq_token = eq_tok, |
| | 513 | .mut_token = mut_tok, |
| | 514 | .comptime_token = null, |
| | 515 | .extern_export_token = null, |
| | 516 | .lib_name = null, |
| | 517 | .type_node = null, |
| | 518 | .align_node = null, |
| | 519 | .section_node = null, |
| | 520 | .init_node = init_node, |
| | 521 | .semicolon_token = try appendToken(c, .Semicolon, ";"), |
| | 522 | }; |
| | 523 | return addTopLevelDecl(c, alias.alias, &node.base); |
| | 524 | } |
| | 525 | |
| 429 | const ResultUsed = enum { | 526 | const ResultUsed = enum { |
| 430 | used, | 527 | used, |
| 431 | unused, | 528 | unused, |
| ... | @@ -442,7 +539,7 @@ fn transStmt( | ... | @@ -442,7 +539,7 @@ fn transStmt( |
| 442 | stmt: *const ZigClangStmt, | 539 | stmt: *const ZigClangStmt, |
| 443 | result_used: ResultUsed, | 540 | result_used: ResultUsed, |
| 444 | lrvalue: LRValue, | 541 | lrvalue: LRValue, |
| 445 | ) !TransResult { | 542 | ) TransError!TransResult { |
| 446 | const sc = ZigClangStmt_getStmtClass(stmt); | 543 | const sc = ZigClangStmt_getStmtClass(stmt); |
| 447 | switch (sc) { | 544 | switch (sc) { |
| 448 | .BinaryOperatorClass => return transBinaryOperator(rp, scope, @ptrCast(*const ZigClangBinaryOperator, stmt), result_used), | 545 | .BinaryOperatorClass => return transBinaryOperator(rp, scope, @ptrCast(*const ZigClangBinaryOperator, stmt), result_used), |
| ... | @@ -456,6 +553,7 @@ fn transStmt( | ... | @@ -456,6 +553,7 @@ fn transStmt( |
| 456 | .StringLiteralClass => return transStringLiteral(rp, scope, @ptrCast(*const ZigClangStringLiteral, stmt), result_used), | 553 | .StringLiteralClass => return transStringLiteral(rp, scope, @ptrCast(*const ZigClangStringLiteral, stmt), result_used), |
| 457 | .ParenExprClass => return transExpr(rp, scope, ZigClangParenExpr_getSubExpr(@ptrCast(*const ZigClangParenExpr, stmt)), result_used, lrvalue), | 554 | .ParenExprClass => return transExpr(rp, scope, ZigClangParenExpr_getSubExpr(@ptrCast(*const ZigClangParenExpr, stmt)), result_used, lrvalue), |
| 458 | .InitListExprClass => return transInitListExpr(rp, scope, @ptrCast(*const ZigClangInitListExpr, stmt), result_used), | 555 | .InitListExprClass => return transInitListExpr(rp, scope, @ptrCast(*const ZigClangInitListExpr, stmt), result_used), |
| | 556 | .ImplicitValueInitExprClass => return transImplicitValueInitExpr(rp, scope, @ptrCast(*const ZigClangExpr, stmt), result_used), |
| 459 | else => { | 557 | else => { |
| 460 | return revertAndWarn( | 558 | return revertAndWarn( |
| 461 | rp, | 559 | rp, |
| ... | @@ -800,6 +898,13 @@ fn transImplicitCastExpr( | ... | @@ -800,6 +898,13 @@ fn transImplicitCastExpr( |
| 800 | .LValueToRValue, .NoOp => { | 898 | .LValueToRValue, .NoOp => { |
| 801 | return transExpr(rp, scope, sub_expr, .used, .r_value); | 899 | return transExpr(rp, scope, sub_expr, .used, .r_value); |
| 802 | }, | 900 | }, |
| | 901 | .NullToPointer => { |
| | 902 | return TransResult{ |
| | 903 | .node = try transCreateNodeNullLiteral(rp.c), |
| | 904 | .node_scope = scope, |
| | 905 | .child_scope = scope, |
| | 906 | }; |
| | 907 | }, |
| 803 | else => |kind| return revertAndWarn( | 908 | else => |kind| return revertAndWarn( |
| 804 | rp, | 909 | rp, |
| 805 | error.UnsupportedTranslation, | 910 | error.UnsupportedTranslation, |
| ... | @@ -984,21 +1089,33 @@ fn transInitListExpr( | ... | @@ -984,21 +1089,33 @@ fn transInitListExpr( |
| 984 | expr: *const ZigClangInitListExpr, | 1089 | expr: *const ZigClangInitListExpr, |
| 985 | used: ResultUsed, | 1090 | used: ResultUsed, |
| 986 | ) TransError!TransResult { | 1091 | ) TransError!TransResult { |
| 987 | // TODO use anon literals once they work properly | | |
| 988 | const qt = getExprQualType(rp.c, @ptrCast(*const ZigClangExpr, expr)); | 1092 | const qt = getExprQualType(rp.c, @ptrCast(*const ZigClangExpr, expr)); |
| 989 | const qual_type = ZigClangQualType_getTypePtr(qt); | 1093 | const qual_type = ZigClangQualType_getTypePtr(qt); |
| 990 | const source_loc = ZigClangExpr_getBeginLoc(@ptrCast(*const ZigClangExpr, expr)); | 1094 | const source_loc = ZigClangExpr_getBeginLoc(@ptrCast(*const ZigClangExpr, expr)); |
| | 1095 | switch (ZigClangType_getTypeClass(qual_type)) { |
| | 1096 | .ConstantArray => {}, |
| | 1097 | .Record, .Elaborated => { |
| | 1098 | return revertAndWarn(rp, error.UnsupportedType, source_loc, "TODO initListExpr for structs", .{}); |
| | 1099 | }, |
| | 1100 | else => { |
| | 1101 | const type_name = rp.c.str(ZigClangType_getTypeClassName(qual_type)); |
| | 1102 | return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported initlist type: '{}'", .{type_name}); |
| | 1103 | }, |
| | 1104 | } |
| | 1105 | |
| 991 | const arr_type = ZigClangType_getAsArrayTypeUnsafe(qual_type); | 1106 | const arr_type = ZigClangType_getAsArrayTypeUnsafe(qual_type); |
| 992 | const child_qt = ZigClangArrayType_getElementType(arr_type); | 1107 | const child_qt = ZigClangArrayType_getElementType(arr_type); |
| 993 | const init_count = ZigClangInitListExpr_getNumInits(expr); | 1108 | const init_count = ZigClangInitListExpr_getNumInits(expr); |
| 994 | const all_count = 200; //ZigClangArrayType_getSize(arr_type); | 1109 | const const_arr_ty = @ptrCast(*const ZigClangConstantArrayType, qual_type); |
| | 1110 | const size_ap_int = ZigClangConstantArrayType_getSize(const_arr_ty); |
| | 1111 | const all_count = ZigClangAPInt_getLimitedValue(size_ap_int, std.math.maxInt(usize)); |
| 995 | const leftover_count = all_count - init_count; | 1112 | const leftover_count = all_count - init_count; |
| 996 | | 1113 | |
| 997 | var init_node: *ast.Node.SuffixOp = undefined; | 1114 | var init_node: *ast.Node.SuffixOp = undefined; |
| 998 | var cat_tok: ast.TokenIndex = undefined; | 1115 | var cat_tok: ast.TokenIndex = undefined; |
| 999 | if (init_count != 0) { | 1116 | if (init_count != 0) { |
| 1000 | var type_node = try transQualType(rp, qt, source_loc); | 1117 | const dot_tok = try appendToken(rp.c, .Period, "."); |
| 1001 | init_node = try transCreateNodeArrayInitializer(rp.c, type_node); | 1118 | init_node = try transCreateNodeArrayInitializer(rp.c, dot_tok); |
| 1002 | var i: c_uint = 0; | 1119 | var i: c_uint = 0; |
| 1003 | while (i < init_count) : (i += 1) { | 1120 | while (i < init_count) : (i += 1) { |
| 1004 | const elem_expr = ZigClangInitListExpr_getInit(expr, i); | 1121 | const elem_expr = ZigClangInitListExpr_getInit(expr, i); |
| ... | @@ -1016,8 +1133,8 @@ fn transInitListExpr( | ... | @@ -1016,8 +1133,8 @@ fn transInitListExpr( |
| 1016 | cat_tok = try appendToken(rp.c, .PlusPlus, "++"); | 1133 | cat_tok = try appendToken(rp.c, .PlusPlus, "++"); |
| 1017 | } | 1134 | } |
| 1018 | | 1135 | |
| 1019 | var filler_type_node = try transQualType(rp, qt, source_loc); | 1136 | const dot_tok = try appendToken(rp.c, .Period, "."); |
| 1020 | var filler_init_node = try transCreateNodeArrayInitializer(rp.c, filler_type_node); | 1137 | var filler_init_node = try transCreateNodeArrayInitializer(rp.c, dot_tok); |
| 1021 | const filler_val_expr = ZigClangInitListExpr_getArrayFiller(expr); | 1138 | const filler_val_expr = ZigClangInitListExpr_getArrayFiller(expr); |
| 1022 | try filler_init_node.op.ArrayInitializer.push((try transExpr(rp, scope, filler_val_expr, .used, .r_value)).node); | 1139 | try filler_init_node.op.ArrayInitializer.push((try transExpr(rp, scope, filler_val_expr, .used, .r_value)).node); |
| 1023 | filler_init_node.rtoken = try appendToken(rp.c, .RBrace, "}"); | 1140 | filler_init_node.rtoken = try appendToken(rp.c, .RBrace, "}"); |
| ... | @@ -1060,6 +1177,58 @@ fn transInitListExpr( | ... | @@ -1060,6 +1177,58 @@ fn transInitListExpr( |
| 1060 | }; | 1177 | }; |
| 1061 | } | 1178 | } |
| 1062 | | 1179 | |
| | 1180 | fn transImplicitValueInitExpr( |
| | 1181 | rp: RestorePoint, |
| | 1182 | scope: *Scope, |
| | 1183 | expr: *const ZigClangExpr, |
| | 1184 | used: ResultUsed, |
| | 1185 | ) TransError!TransResult { |
| | 1186 | const source_loc = ZigClangExpr_getBeginLoc(expr); |
| | 1187 | const qt = getExprQualType(rp.c, expr); |
| | 1188 | const ty = ZigClangQualType_getTypePtr(qt); |
| | 1189 | const node = switch (ZigClangType_getTypeClass(ty)) { |
| | 1190 | .Builtin => blk: { |
| | 1191 | const builtin_ty = @ptrCast(*const ZigClangBuiltinType, ty); |
| | 1192 | switch (ZigClangBuiltinType_getKind(builtin_ty)) { |
| | 1193 | .Bool => { |
| | 1194 | break :blk try transCreateNodeBoolLiteral(rp.c, false); |
| | 1195 | }, |
| | 1196 | .Char_U, |
| | 1197 | .UChar, |
| | 1198 | .Char_S, |
| | 1199 | .Char8, |
| | 1200 | .SChar, |
| | 1201 | .UShort, |
| | 1202 | .UInt, |
| | 1203 | .ULong, |
| | 1204 | .ULongLong, |
| | 1205 | .Short, |
| | 1206 | .Int, |
| | 1207 | .Long, |
| | 1208 | .LongLong, |
| | 1209 | .UInt128, |
| | 1210 | .Int128, |
| | 1211 | .Float, |
| | 1212 | .Double, |
| | 1213 | .Float128, |
| | 1214 | .Float16, |
| | 1215 | .LongDouble, |
| | 1216 | => { |
| | 1217 | break :blk try transCreateNodeInt(rp.c, 0); |
| | 1218 | }, |
| | 1219 | else => return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported builtin type", .{}), |
| | 1220 | } |
| | 1221 | }, |
| | 1222 | .Pointer => try transCreateNodeNullLiteral(rp.c), |
| | 1223 | else => return revertAndWarn(rp, error.UnsupportedType, source_loc, "type does not have an implicit init value", .{}), |
| | 1224 | }; |
| | 1225 | return TransResult{ |
| | 1226 | .node = node, |
| | 1227 | .child_scope = scope, |
| | 1228 | .node_scope = scope, |
| | 1229 | }; |
| | 1230 | } |
| | 1231 | |
| 1063 | fn findBlockScope(inner: *Scope) *Scope.Block { | 1232 | fn findBlockScope(inner: *Scope) *Scope.Block { |
| 1064 | var scope = inner; | 1233 | var scope = inner; |
| 1065 | while (true) : (scope = scope.parent orelse unreachable) { | 1234 | while (true) : (scope = scope.parent orelse unreachable) { |
| ... | @@ -1142,28 +1311,120 @@ fn maybeSuppressResult( | ... | @@ -1142,28 +1311,120 @@ fn maybeSuppressResult( |
| 1142 | | 1311 | |
| 1143 | fn addTopLevelDecl(c: *Context, name: []const u8, decl_node: *ast.Node) !void { | 1312 | fn addTopLevelDecl(c: *Context, name: []const u8, decl_node: *ast.Node) !void { |
| 1144 | try c.tree.root_node.decls.push(decl_node); | 1313 | try c.tree.root_node.decls.push(decl_node); |
| | 1314 | _ = try c.sym_table.put(name, {}); |
| 1145 | } | 1315 | } |
| 1146 | | 1316 | |
| 1147 | fn transQualType(rp: RestorePoint, qt: ZigClangQualType, source_loc: ZigClangSourceLocation) TypeError!*ast.Node { | 1317 | fn transQualType(rp: RestorePoint, qt: ZigClangQualType, source_loc: ZigClangSourceLocation) TypeError!*ast.Node { |
| 1148 | return transType(rp, ZigClangQualType_getTypePtr(qt), source_loc); | 1318 | return transType(rp, ZigClangQualType_getTypePtr(qt), source_loc); |
| 1149 | } | 1319 | } |
| 1150 | | 1320 | |
| | 1321 | fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) TypeError!*ast.Node { |
| | 1322 | const rp = makeRestorePoint(c); |
| | 1323 | |
| | 1324 | const record_loc = ZigClangRecordDecl_getLocation(record_decl); |
| | 1325 | |
| | 1326 | var container_kind_name: []const u8 = undefined; |
| | 1327 | var container_kind: std.zig.Token.Id = undefined; |
| | 1328 | |
| | 1329 | if (ZigClangRecordDecl_isUnion(record_decl)) { |
| | 1330 | container_kind_name = "union"; |
| | 1331 | container_kind = .Keyword_union; |
| | 1332 | } else if (ZigClangRecordDecl_isStruct(record_decl)) { |
| | 1333 | container_kind_name = "struct"; |
| | 1334 | container_kind = .Keyword_struct; |
| | 1335 | } else { |
| | 1336 | return revertAndWarn( |
| | 1337 | rp, |
| | 1338 | error.UnsupportedType, |
| | 1339 | record_loc, |
| | 1340 | "unsupported record type", |
| | 1341 | .{}, |
| | 1342 | ); |
| | 1343 | } |
| | 1344 | |
| | 1345 | const record_def = ZigClangRecordDecl_getDefinition(record_decl) orelse { |
| | 1346 | return transCreateNodeOpaqueType(c); |
| | 1347 | }; |
| | 1348 | |
| | 1349 | const extern_tok = try appendToken(c, .Keyword_extern, "extern"); |
| | 1350 | const container_tok = try appendToken(c, container_kind, container_kind_name); |
| | 1351 | const lbrace_token = try appendToken(c, .LBrace, "{"); |
| | 1352 | |
| | 1353 | const container_node = try c.a().create(ast.Node.ContainerDecl); |
| | 1354 | container_node.* = .{ |
| | 1355 | .base = ast.Node{ .id = .ContainerDecl }, |
| | 1356 | .layout_token = extern_tok, |
| | 1357 | .kind_token = container_tok, |
| | 1358 | .init_arg_expr = .None, |
| | 1359 | .fields_and_decls = ast.Node.ContainerDecl.DeclList.init(c.a()), |
| | 1360 | .lbrace_token = lbrace_token, |
| | 1361 | .rbrace_token = undefined, |
| | 1362 | }; |
| | 1363 | |
| | 1364 | var it = ZigClangRecordDecl_field_begin(record_def); |
| | 1365 | const end_it = ZigClangRecordDecl_field_end(record_def); |
| | 1366 | while (ZigClangRecordDecl_field_iterator_neq(it, end_it)) : (it = ZigClangRecordDecl_field_iterator_next(it)) { |
| | 1367 | const field_decl = ZigClangRecordDecl_field_iterator_deref(it); |
| | 1368 | const field_loc = ZigClangFieldDecl_getLocation(field_decl); |
| | 1369 | |
| | 1370 | if (ZigClangFieldDecl_isBitField(field_decl)) { |
| | 1371 | rp.activate(); |
| | 1372 | const node = try transCreateNodeOpaqueType(c); |
| | 1373 | try emitWarning(c, field_loc, "{} demoted to opaque type - has bitfield", .{container_kind_name}); |
| | 1374 | return node; |
| | 1375 | } |
| | 1376 | |
| | 1377 | const field_name = try appendToken(c, .Identifier, try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, field_decl)))); |
| | 1378 | _ = try appendToken(c, .Colon, ":"); |
| | 1379 | const field_type = try transQualType(rp, ZigClangFieldDecl_getType(field_decl), field_loc); |
| | 1380 | |
| | 1381 | const field_node = try c.a().create(ast.Node.ContainerField); |
| | 1382 | field_node.* = .{ |
| | 1383 | .doc_comments = null, |
| | 1384 | .comptime_token = null, |
| | 1385 | .name_token = field_name, |
| | 1386 | .type_expr = field_type, |
| | 1387 | .value_expr = null, |
| | 1388 | .align_expr = null, |
| | 1389 | }; |
| | 1390 | |
| | 1391 | try container_node.fields_and_decls.push(&field_node.base); |
| | 1392 | _ = try appendToken(c, .Comma, ","); |
| | 1393 | } |
| | 1394 | |
| | 1395 | container_node.rbrace_token = try appendToken(c, .RBrace, "}"); |
| | 1396 | return &container_node.base; |
| | 1397 | } |
| | 1398 | |
| 1151 | fn qualTypeIsPtr(qt: ZigClangQualType) bool { | 1399 | fn qualTypeIsPtr(qt: ZigClangQualType) bool { |
| 1152 | return ZigClangType_getTypeClass(qualTypeCanon(qt)) == .Pointer; | 1400 | return ZigClangType_getTypeClass(qualTypeCanon(qt)) == .Pointer; |
| 1153 | } | 1401 | } |
| 1154 | | 1402 | |
| 1155 | fn qualTypeChildIsFnProto(qt: ZigClangQualType) bool { | 1403 | fn qualTypeChildIsFnProto(qt: ZigClangQualType) bool { |
| 1156 | const ty = ZigClangQualType_getTypePtr(qt); | 1404 | const ty = ZigClangQualType_getTypePtr(qt); |
| 1157 | if (ZigClangType_getTypeClass(ty) == .Paren) { | 1405 | |
| 1158 | const paren_type = @ptrCast(*const ZigClangParenType, ty); | 1406 | switch (ZigClangType_getTypeClass(ty)) { |
| 1159 | const inner_type = ZigClangParenType_getInnerType(paren_type); | 1407 | .FunctionProto, .FunctionNoProto => return true, |
| 1160 | return ZigClangQualType_getTypeClass(inner_type) == .FunctionProto; | 1408 | .Elaborated => { |
| 1161 | } | 1409 | const elaborated_ty = @ptrCast(*const ZigClangElaboratedType, ty); |
| 1162 | if (ZigClangType_getTypeClass(ty) == .Attributed) { | 1410 | return qualTypeChildIsFnProto(ZigClangElaboratedType_getNamedType(elaborated_ty)); |
| 1163 | const attr_type = @ptrCast(*const ZigClangAttributedType, ty); | 1411 | }, |
| 1164 | return qualTypeChildIsFnProto(ZigClangAttributedType_getEquivalentType(attr_type)); | 1412 | .Typedef => { |
| | 1413 | const typedef_ty = @ptrCast(*const ZigClangTypedefType, ty); |
| | 1414 | const typedef_decl = ZigClangTypedefType_getDecl(typedef_ty); |
| | 1415 | return qualTypeChildIsFnProto(ZigClangTypedefNameDecl_getUnderlyingType(typedef_decl)); |
| | 1416 | }, |
| | 1417 | .Paren => { |
| | 1418 | const paren_type = @ptrCast(*const ZigClangParenType, ty); |
| | 1419 | const inner_type = ZigClangParenType_getInnerType(paren_type); |
| | 1420 | return ZigClangQualType_getTypeClass(inner_type) == .FunctionProto; |
| | 1421 | }, |
| | 1422 | .Attributed => { |
| | 1423 | const attr_type = @ptrCast(*const ZigClangAttributedType, ty); |
| | 1424 | return qualTypeChildIsFnProto(ZigClangAttributedType_getEquivalentType(attr_type)); |
| | 1425 | }, |
| | 1426 | else => return false, |
| 1165 | } | 1427 | } |
| 1166 | return false; | | |
| 1167 | } | 1428 | } |
| 1168 | | 1429 | |
| 1169 | fn qualTypeCanon(qt: ZigClangQualType) *const ZigClangType { | 1430 | fn qualTypeCanon(qt: ZigClangQualType) *const ZigClangType { |
| ... | @@ -1197,7 +1458,18 @@ fn typeIsOpaque(c: *Context, ty: *const ZigClangType, loc: ZigClangSourceLocatio | ... | @@ -1197,7 +1458,18 @@ fn typeIsOpaque(c: *Context, ty: *const ZigClangType, loc: ZigClangSourceLocatio |
| 1197 | .Record => { | 1458 | .Record => { |
| 1198 | const record_ty = @ptrCast(*const ZigClangRecordType, ty); | 1459 | const record_ty = @ptrCast(*const ZigClangRecordType, ty); |
| 1199 | const record_decl = ZigClangRecordType_getDecl(record_ty); | 1460 | const record_decl = ZigClangRecordType_getDecl(record_ty); |
| 1200 | return (ZigClangRecordDecl_getDefinition(record_decl) == null); | 1461 | const record_def = ZigClangRecordDecl_getDefinition(record_decl) orelse |
| | 1462 | return true; |
| | 1463 | var it = ZigClangRecordDecl_field_begin(record_def); |
| | 1464 | const end_it = ZigClangRecordDecl_field_end(record_def); |
| | 1465 | while (ZigClangRecordDecl_field_iterator_neq(it, end_it)) : (it = ZigClangRecordDecl_field_iterator_next(it)) { |
| | 1466 | const field_decl = ZigClangRecordDecl_field_iterator_deref(it); |
| | 1467 | |
| | 1468 | if (ZigClangFieldDecl_isBitField(field_decl)) { |
| | 1469 | return true; |
| | 1470 | } |
| | 1471 | } |
| | 1472 | return false; |
| 1201 | }, | 1473 | }, |
| 1202 | .Elaborated => { | 1474 | .Elaborated => { |
| 1203 | const elaborated_ty = @ptrCast(*const ZigClangElaboratedType, ty); | 1475 | const elaborated_ty = @ptrCast(*const ZigClangElaboratedType, ty); |
| ... | @@ -1435,12 +1707,35 @@ fn transCreateNodeUndefinedLiteral(c: *Context) !*ast.Node { | ... | @@ -1435,12 +1707,35 @@ fn transCreateNodeUndefinedLiteral(c: *Context) !*ast.Node { |
| 1435 | return &node.base; | 1707 | return &node.base; |
| 1436 | } | 1708 | } |
| 1437 | | 1709 | |
| 1438 | fn transCreateNodeArrayInitializer(c: *Context, type_node: *ast.Node) !*ast.Node.SuffixOp { | 1710 | fn transCreateNodeNullLiteral(c: *Context) !*ast.Node { |
| | 1711 | const token = try appendToken(c, .Keyword_null, "null"); |
| | 1712 | const node = try c.a().create(ast.Node.NullLiteral); |
| | 1713 | node.* = ast.Node.NullLiteral{ |
| | 1714 | .base = ast.Node{ .id = .NullLiteral }, |
| | 1715 | .token = token, |
| | 1716 | }; |
| | 1717 | return &node.base; |
| | 1718 | } |
| | 1719 | |
| | 1720 | fn transCreateNodeBoolLiteral(c: *Context, value: bool) !*ast.Node { |
| | 1721 | const token = if (value) |
| | 1722 | try appendToken(c, .Keyword_true, "true") |
| | 1723 | else |
| | 1724 | try appendToken(c, .Keyword_false, "false"); |
| | 1725 | const node = try c.a().create(ast.Node.BoolLiteral); |
| | 1726 | node.* = ast.Node.BoolLiteral{ |
| | 1727 | .base = ast.Node{ .id = .BoolLiteral }, |
| | 1728 | .token = token, |
| | 1729 | }; |
| | 1730 | return &node.base; |
| | 1731 | } |
| | 1732 | |
| | 1733 | fn transCreateNodeArrayInitializer(c: *Context, dot_tok: ast.TokenIndex) !*ast.Node.SuffixOp { |
| 1439 | _ = try appendToken(c, .LBrace, "{"); | 1734 | _ = try appendToken(c, .LBrace, "{"); |
| 1440 | const node = try c.a().create(ast.Node.SuffixOp); | 1735 | const node = try c.a().create(ast.Node.SuffixOp); |
| 1441 | node.* = ast.Node.SuffixOp{ | 1736 | node.* = ast.Node.SuffixOp{ |
| 1442 | .base = ast.Node{ .id = .SuffixOp }, | 1737 | .base = ast.Node{ .id = .SuffixOp }, |
| 1443 | .lhs = .{ .node = type_node }, | 1738 | .lhs = .{ .dot = dot_tok }, |
| 1444 | .op = .{ | 1739 | .op = .{ |
| 1445 | .ArrayInitializer = ast.Node.SuffixOp.Op.InitList.init(c.a()), | 1740 | .ArrayInitializer = ast.Node.SuffixOp.Op.InitList.init(c.a()), |
| 1446 | }, | 1741 | }, |
| ... | @@ -1450,7 +1745,7 @@ fn transCreateNodeArrayInitializer(c: *Context, type_node: *ast.Node) !*ast.Node | ... | @@ -1450,7 +1745,7 @@ fn transCreateNodeArrayInitializer(c: *Context, type_node: *ast.Node) !*ast.Node |
| 1450 | } | 1745 | } |
| 1451 | | 1746 | |
| 1452 | fn transCreateNodeInt(c: *Context, int: var) !*ast.Node { | 1747 | fn transCreateNodeInt(c: *Context, int: var) !*ast.Node { |
| 1453 | const token = try appendToken(c, .IntegerLiteral, try std.fmt.allocPrint(c.a(), "{}", .{int})); | 1748 | const token = try appendTokenFmt(c, .IntegerLiteral, "{}", .{int}); |
| 1454 | const node = try c.a().create(ast.Node.IntegerLiteral); | 1749 | const node = try c.a().create(ast.Node.IntegerLiteral); |
| 1455 | node.* = ast.Node.IntegerLiteral{ | 1750 | node.* = ast.Node.IntegerLiteral{ |
| 1456 | .base = ast.Node{ .id = .IntegerLiteral }, | 1751 | .base = ast.Node{ .id = .IntegerLiteral }, |
| ... | @@ -1459,6 +1754,21 @@ fn transCreateNodeInt(c: *Context, int: var) !*ast.Node { | ... | @@ -1459,6 +1754,21 @@ fn transCreateNodeInt(c: *Context, int: var) !*ast.Node { |
| 1459 | return &node.base; | 1754 | return &node.base; |
| 1460 | } | 1755 | } |
| 1461 | | 1756 | |
| | 1757 | fn transCreateNodeOpaqueType(c: *Context) !*ast.Node { |
| | 1758 | const builtin_tok = try appendToken(c, .Builtin, "@OpaqueType"); |
| | 1759 | _ = try appendToken(c, .LParen, "("); |
| | 1760 | const rparen_tok = try appendToken(c, .RParen, ")"); |
| | 1761 | |
| | 1762 | const call_node = try c.a().create(ast.Node.BuiltinCall); |
| | 1763 | call_node.* = ast.Node.BuiltinCall{ |
| | 1764 | .base = ast.Node{ .id = ast.Node.Id.BuiltinCall }, |
| | 1765 | .builtin_token = builtin_tok, |
| | 1766 | .params = ast.Node.BuiltinCall.ParamList.init(c.a()), |
| | 1767 | .rparen_token = rparen_tok, |
| | 1768 | }; |
| | 1769 | return &call_node.base; |
| | 1770 | } |
| | 1771 | |
| 1462 | const RestorePoint = struct { | 1772 | const RestorePoint = struct { |
| 1463 | c: *Context, | 1773 | c: *Context, |
| 1464 | token_index: ast.TokenIndex, | 1774 | token_index: ast.TokenIndex, |
| ... | @@ -1583,6 +1893,19 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour | ... | @@ -1583,6 +1893,19 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour |
| 1583 | const typedef_name = try rp.c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, typedef_decl))); | 1893 | const typedef_name = try rp.c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, typedef_decl))); |
| 1584 | return appendIdentifier(rp.c, typedef_name); | 1894 | return appendIdentifier(rp.c, typedef_name); |
| 1585 | }, | 1895 | }, |
| | 1896 | .Record => { |
| | 1897 | const record_ty = @ptrCast(*const ZigClangRecordType, ty); |
| | 1898 | |
| | 1899 | const record_decl = ZigClangRecordType_getDecl(record_ty); |
| | 1900 | if (try getContainerName(rp.c, record_decl)) |name| |
| | 1901 | return appendIdentifier(rp.c, name) |
| | 1902 | else |
| | 1903 | return transRecordDecl(rp.c, record_decl); |
| | 1904 | }, |
| | 1905 | .Elaborated => { |
| | 1906 | const elaborated_ty = @ptrCast(*const ZigClangElaboratedType, ty); |
| | 1907 | return transQualType(rp, ZigClangElaboratedType_getNamedType(elaborated_ty), source_loc); |
| | 1908 | }, |
| 1586 | else => { | 1909 | else => { |
| 1587 | const type_name = rp.c.str(ZigClangType_getTypeClassName(ty)); | 1910 | const type_name = rp.c.str(ZigClangType_getTypeClassName(ty)); |
| 1588 | return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported type: '{}'", .{type_name}); | 1911 | return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported type: '{}'", .{type_name}); |
| ... | @@ -1590,6 +1913,24 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour | ... | @@ -1590,6 +1913,24 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour |
| 1590 | } | 1913 | } |
| 1591 | } | 1914 | } |
| 1592 | | 1915 | |
| | 1916 | fn getContainerName(c: *Context, record_decl: *const ZigClangRecordDecl) !?[]const u8 { |
| | 1917 | const bare_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, record_decl))); |
| | 1918 | |
| | 1919 | const container_kind_name = if (ZigClangRecordDecl_isUnion(record_decl)) |
| | 1920 | "union" |
| | 1921 | else if (ZigClangRecordDecl_isStruct(record_decl)) |
| | 1922 | "struct" |
| | 1923 | else { |
| | 1924 | try emitWarning(c, ZigClangRecordDecl_getLocation(record_decl), "record {} is not a struct or union", .{bare_name}); |
| | 1925 | return null; |
| | 1926 | }; |
| | 1927 | |
| | 1928 | if (ZigClangRecordDecl_isAnonymousStructOrUnion(record_decl) or bare_name.len == 0) |
| | 1929 | return null; |
| | 1930 | |
| | 1931 | return try std.fmt.allocPrint(c.a(), "{}_{}", .{ container_kind_name, bare_name }); |
| | 1932 | } |
| | 1933 | |
| 1593 | fn isCVoid(qt: ZigClangQualType) bool { | 1934 | fn isCVoid(qt: ZigClangQualType) bool { |
| 1594 | const ty = ZigClangQualType_getTypePtr(qt); | 1935 | const ty = ZigClangQualType_getTypePtr(qt); |
| 1595 | if (ZigClangType_getTypeClass(ty) == .Builtin) { | 1936 | if (ZigClangType_getTypeClass(ty) == .Builtin) { |