| ... | ... | @@ -15,7 +15,7 @@ pub const Error = error{OutOfMemory}; |
| 15 | 15 | const TypeError = Error || error{UnsupportedType}; |
| 16 | 16 | const TransError = TypeError || error{UnsupportedTranslation}; |
| 17 | 17 | |
| 18 | | const DeclTable = std.HashMap(usize, []const u8, addrHash, addrEql); |
| 18 | const DeclTable = std.HashMap(usize, void, addrHash, addrEql); |
| 19 | 19 | |
| 20 | 20 | fn addrHash(x: usize) u32 { |
| 21 | 21 | switch (@typeInfo(usize).Int.bits) { |
| ... | ... | @@ -31,6 +31,12 @@ fn addrEql(a: usize, b: usize) bool { |
| 31 | 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 | 40 | const Scope = struct { |
| 35 | 41 | id: Id, |
| 36 | 42 | parent: ?*Scope, |
| ... | ... | @@ -98,6 +104,8 @@ const Context = struct { |
| 98 | 104 | err: Error, |
| 99 | 105 | source_manager: *ZigClangSourceManager, |
| 100 | 106 | decl_table: DeclTable, |
| 107 | alias_list: AliasList, |
| 108 | sym_table: SymbolTable, |
| 101 | 109 | global_scope: *Scope.Root, |
| 102 | 110 | ptr_params: std.BufSet, |
| 103 | 111 | clang_context: *ZigClangASTContext, |
| ... | ... | @@ -177,6 +185,8 @@ pub fn translate( |
| 177 | 185 | .source_manager = ZigClangASTUnit_getSourceManager(ast_unit), |
| 178 | 186 | .err = undefined, |
| 179 | 187 | .decl_table = DeclTable.init(arena), |
| 188 | .alias_list = AliasList.init(arena), |
| 189 | .sym_table = SymbolTable.init(arena), |
| 180 | 190 | .global_scope = try arena.create(Scope.Root), |
| 181 | 191 | .ptr_params = std.BufSet.init(arena), |
| 182 | 192 | .clang_context = ZigClangASTUnit_getASTContext(ast_unit).?, |
| ... | ... | @@ -191,10 +201,15 @@ pub fn translate( |
| 191 | 201 | if (!ZigClangASTUnit_visitLocalTopLevelDecls(ast_unit, &context, declVisitorC)) { |
| 192 | 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 | 211 | tree.root_node.eof_token = try appendToken(&context, .Eof, ""); |
| 196 | 212 | tree.source = source_buffer.toOwnedSlice(); |
| 197 | | |
| 198 | 213 | if (false) { |
| 199 | 214 | std.debug.warn("debug source:\n{}\n==EOF==\ntokens:\n", tree.source); |
| 200 | 215 | var i: usize = 0; |
| ... | ... | @@ -240,10 +255,9 @@ fn declVisitor(c: *Context, decl: *const ZigClangDecl) Error!void { |
| 240 | 255 | } |
| 241 | 256 | |
| 242 | 257 | fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void { |
| 243 | | if (c.decl_table.contains(@ptrToInt(fn_decl))) return; // Avoid processing this decl twice |
| 258 | if (try c.decl_table.put(@ptrToInt(fn_decl), {})) |_| return; // Avoid processing this decl twice |
| 244 | 259 | const rp = makeRestorePoint(c); |
| 245 | 260 | const fn_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, fn_decl))); |
| 246 | | _ = try c.decl_table.put(@ptrToInt(fn_decl), fn_name); |
| 247 | 261 | const fn_decl_loc = ZigClangFunctionDecl_getLocation(fn_decl); |
| 248 | 262 | const fn_qt = ZigClangFunctionDecl_getType(fn_decl); |
| 249 | 263 | const fn_type = ZigClangQualType_getTypePtr(fn_qt); |
| ... | ... | @@ -305,7 +319,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void { |
| 305 | 319 | } |
| 306 | 320 | |
| 307 | 321 | fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void { |
| 308 | | if (c.decl_table.contains(@ptrToInt(var_decl))) return; // Avoid processing this decl twice |
| 322 | if (try c.decl_table.put(@ptrToInt(var_decl), {})) |_| return; // Avoid processing this decl twice |
| 309 | 323 | const rp = makeRestorePoint(c); |
| 310 | 324 | const visib_tok = try appendToken(c, .Keyword_pub, "pub"); |
| 311 | 325 | |
| ... | ... | @@ -316,7 +330,6 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void { |
| 316 | 330 | |
| 317 | 331 | var scope = &c.global_scope.base; |
| 318 | 332 | const var_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, var_decl))); |
| 319 | | _ = try c.decl_table.put(@ptrToInt(var_decl), var_name); |
| 320 | 333 | const var_decl_loc = ZigClangVarDecl_getLocation(var_decl); |
| 321 | 334 | |
| 322 | 335 | const qual_type = ZigClangVarDecl_getTypeSourceInfo_getType(var_decl); |
| ... | ... | @@ -388,13 +401,12 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void { |
| 388 | 401 | } |
| 389 | 402 | |
| 390 | 403 | fn resolveTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl) Error!void { |
| 391 | | if (c.decl_table.contains(@ptrToInt(ZigClangTypedefNameDecl_getCanonicalDecl(typedef_decl)))) return; // Avoid processing this decl twice |
| 404 | if (try c.decl_table.put(@ptrToInt(ZigClangTypedefNameDecl_getCanonicalDecl(typedef_decl)), {})) |_| return; // Avoid processing this decl twice |
| 392 | 405 | const rp = makeRestorePoint(c); |
| 393 | 406 | const visib_tok = try appendToken(c, .Keyword_pub, "pub"); |
| 394 | 407 | const const_tok = try appendToken(c, .Keyword_const, "const"); |
| 395 | 408 | |
| 396 | 409 | const typedef_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, typedef_decl))); |
| 397 | | _ = try c.decl_table.put(@ptrToInt(ZigClangTypedefNameDecl_getCanonicalDecl(typedef_decl)), typedef_name); |
| 398 | 410 | const name_tok = try appendToken(c, .Identifier, typedef_name); |
| 399 | 411 | const eq_tok = try appendToken(c, .Equal, "="); |
| 400 | 412 | |
| ... | ... | @@ -429,12 +441,9 @@ fn resolveTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl) Err |
| 429 | 441 | } |
| 430 | 442 | |
| 431 | 443 | fn resolveRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!void { |
| 432 | | if (c.decl_table.contains(@ptrToInt(ZigClangRecordDecl_getCanonicalDecl(record_decl)))) return; // Avoid processing this decl twice |
| 444 | if (try c.decl_table.put(@ptrToInt(ZigClangRecordDecl_getCanonicalDecl(record_decl)), {})) |_| return; // Avoid processing this decl twice |
| 433 | 445 | const rp = makeRestorePoint(c); |
| 434 | 446 | |
| 435 | | const visib_tok = try appendToken(c, .Keyword_pub, "pub"); |
| 436 | | const const_tok = try appendToken(c, .Keyword_const, "const"); |
| 437 | | |
| 438 | 447 | const bare_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, record_decl))); |
| 439 | 448 | |
| 440 | 449 | const container_kind_name = if (ZigClangRecordDecl_isUnion(record_decl)) |
| ... | ... | @@ -447,8 +456,10 @@ fn resolveRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error! |
| 447 | 456 | if (ZigClangRecordDecl_isAnonymousStructOrUnion(record_decl) or bare_name.len == 0) |
| 448 | 457 | return; |
| 449 | 458 | |
| 459 | const visib_tok = try appendToken(c, .Keyword_pub, "pub"); |
| 460 | const const_tok = try appendToken(c, .Keyword_const, "const"); |
| 461 | |
| 450 | 462 | const name = try std.fmt.allocPrint(c.a(), "{}_{}", .{ container_kind_name, bare_name }); |
| 451 | | _ = try c.decl_table.put(@ptrToInt(ZigClangRecordDecl_getCanonicalDecl(record_decl)), name); |
| 452 | 463 | const name_tok = try appendToken(c, .Identifier, name); |
| 453 | 464 | |
| 454 | 465 | const eq_tok = try appendToken(c, .Equal, "="); |
| ... | ... | @@ -480,6 +491,36 @@ fn resolveRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error! |
| 480 | 491 | }; |
| 481 | 492 | |
| 482 | 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); |
| 483 | 524 | } |
| 484 | 525 | |
| 485 | 526 | const ResultUsed = enum { |
| ... | ... | @@ -1063,9 +1104,9 @@ fn transInitListExpr( |
| 1063 | 1104 | } |
| 1064 | 1105 | |
| 1065 | 1106 | const arr_type = ZigClangType_getAsArrayTypeUnsafe(qual_type); |
| 1066 | | const const_arr_ty = @ptrCast(*const ZigClangConstantArrayType, qual_type); |
| 1067 | 1107 | const child_qt = ZigClangArrayType_getElementType(arr_type); |
| 1068 | 1108 | const init_count = ZigClangInitListExpr_getNumInits(expr); |
| 1109 | const const_arr_ty = @ptrCast(*const ZigClangConstantArrayType, qual_type); |
| 1069 | 1110 | const size_ap_int = ZigClangConstantArrayType_getSize(const_arr_ty); |
| 1070 | 1111 | const all_count = ZigClangAPInt_getLimitedValue(size_ap_int, std.math.maxInt(usize)); |
| 1071 | 1112 | const leftover_count = all_count - init_count; |
| ... | ... | @@ -1270,6 +1311,7 @@ fn maybeSuppressResult( |
| 1270 | 1311 | |
| 1271 | 1312 | fn addTopLevelDecl(c: *Context, name: []const u8, decl_node: *ast.Node) !void { |
| 1272 | 1313 | try c.tree.root_node.decls.push(decl_node); |
| 1314 | _ = try c.sym_table.put(name, {}); |
| 1273 | 1315 | } |
| 1274 | 1316 | |
| 1275 | 1317 | fn transQualType(rp: RestorePoint, qt: ZigClangQualType, source_loc: ZigClangSourceLocation) TypeError!*ast.Node { |
| ... | ... | @@ -1316,7 +1358,7 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) TypeErro |
| 1316 | 1358 | .init_arg_expr = .None, |
| 1317 | 1359 | .fields_and_decls = ast.Node.ContainerDecl.DeclList.init(c.a()), |
| 1318 | 1360 | .lbrace_token = lbrace_token, |
| 1319 | | .rbrace_token = undefined, // TODO |
| 1361 | .rbrace_token = undefined, |
| 1320 | 1362 | }; |
| 1321 | 1363 | |
| 1322 | 1364 | var it = ZigClangRecordDecl_field_begin(record_def); |
| ... | ... | @@ -1855,17 +1897,14 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour |
| 1855 | 1897 | const record_ty = @ptrCast(*const ZigClangRecordType, ty); |
| 1856 | 1898 | |
| 1857 | 1899 | const record_decl = ZigClangRecordType_getDecl(record_ty); |
| 1858 | | if (rp.c.decl_table.get(@ptrToInt(ZigClangRecordDecl_getCanonicalDecl(record_decl)))) |kv| |
| 1859 | | return appendIdentifier(rp.c, kv.value) |
| 1900 | if (try getContainerName(rp.c, record_decl)) |name| |
| 1901 | return appendIdentifier(rp.c, name) |
| 1860 | 1902 | else |
| 1861 | 1903 | return transRecordDecl(rp.c, record_decl); |
| 1862 | 1904 | }, |
| 1863 | 1905 | .Elaborated => { |
| 1864 | 1906 | const elaborated_ty = @ptrCast(*const ZigClangElaboratedType, ty); |
| 1865 | | switch (ZigClangElaboratedType_getKeyword(elaborated_ty)) { |
| 1866 | | .Struct, .Enum, .Union => return try transQualType(rp, ZigClangElaboratedType_getNamedType(elaborated_ty), source_loc), |
| 1867 | | else => return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported elaborated type", .{}), |
| 1868 | | } |
| 1907 | return transQualType(rp, ZigClangElaboratedType_getNamedType(elaborated_ty), source_loc); |
| 1869 | 1908 | }, |
| 1870 | 1909 | else => { |
| 1871 | 1910 | const type_name = rp.c.str(ZigClangType_getTypeClassName(ty)); |
| ... | ... | @@ -1874,6 +1913,24 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour |
| 1874 | 1913 | } |
| 1875 | 1914 | } |
| 1876 | 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 | |
| 1877 | 1934 | fn isCVoid(qt: ZigClangQualType) bool { |
| 1878 | 1935 | const ty = ZigClangQualType_getTypePtr(qt); |
| 1879 | 1936 | if (ZigClangType_getTypeClass(ty) == .Builtin) { |