| ... | @@ -15,7 +15,7 @@ pub const Error = error{OutOfMemory}; | ... | @@ -15,7 +15,7 @@ pub const Error = error{OutOfMemory}; |
| 15 | const TypeError = Error || error{UnsupportedType}; | 15 | const TypeError = Error || error{UnsupportedType}; |
| 16 | const TransError = TypeError || error{UnsupportedTranslation}; | 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 | fn addrHash(x: usize) u32 { | 20 | fn addrHash(x: usize) u32 { |
| 21 | switch (@typeInfo(usize).Int.bits) { | 21 | switch (@typeInfo(usize).Int.bits) { |
| ... | @@ -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,10 +201,15 @@ pub fn translate( | ... | @@ -191,10 +201,15 @@ 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(); |
| 197 | | | |
| 198 | if (false) { | 213 | if (false) { |
| 199 | std.debug.warn("debug source:\n{}\n==EOF==\ntokens:\n", tree.source); | 214 | std.debug.warn("debug source:\n{}\n==EOF==\ntokens:\n", tree.source); |
| 200 | var i: usize = 0; | 215 | var i: usize = 0; |
| ... | @@ -240,10 +255,9 @@ fn declVisitor(c: *Context, decl: *const ZigClangDecl) Error!void { | ... | @@ -240,10 +255,9 @@ fn declVisitor(c: *Context, decl: *const ZigClangDecl) Error!void { |
| 240 | } | 255 | } |
| 241 | | 256 | |
| 242 | fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void { | 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 | const rp = makeRestorePoint(c); | 259 | const rp = makeRestorePoint(c); |
| 245 | const fn_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, fn_decl))); | 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 | const fn_decl_loc = ZigClangFunctionDecl_getLocation(fn_decl); | 261 | const fn_decl_loc = ZigClangFunctionDecl_getLocation(fn_decl); |
| 248 | const fn_qt = ZigClangFunctionDecl_getType(fn_decl); | 262 | const fn_qt = ZigClangFunctionDecl_getType(fn_decl); |
| 249 | const fn_type = ZigClangQualType_getTypePtr(fn_qt); | 263 | const fn_type = ZigClangQualType_getTypePtr(fn_qt); |
| ... | @@ -305,7 +319,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void { | ... | @@ -305,7 +319,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void { |
| 305 | } | 319 | } |
| 306 | | 320 | |
| 307 | fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void { | 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 | const rp = makeRestorePoint(c); | 323 | const rp = makeRestorePoint(c); |
| 310 | const visib_tok = try appendToken(c, .Keyword_pub, "pub"); | 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,7 +330,6 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void { |
| 316 | | 330 | |
| 317 | var scope = &c.global_scope.base; | 331 | var scope = &c.global_scope.base; |
| 318 | const var_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, var_decl))); | 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 | const var_decl_loc = ZigClangVarDecl_getLocation(var_decl); | 333 | const var_decl_loc = ZigClangVarDecl_getLocation(var_decl); |
| 321 | | 334 | |
| 322 | const qual_type = ZigClangVarDecl_getTypeSourceInfo_getType(var_decl); | 335 | const qual_type = ZigClangVarDecl_getTypeSourceInfo_getType(var_decl); |
| ... | @@ -388,13 +401,12 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void { | ... | @@ -388,13 +401,12 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void { |
| 388 | } | 401 | } |
| 389 | | 402 | |
| 390 | fn resolveTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl) Error!void { | 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 | const rp = makeRestorePoint(c); | 405 | const rp = makeRestorePoint(c); |
| 393 | const visib_tok = try appendToken(c, .Keyword_pub, "pub"); | 406 | const visib_tok = try appendToken(c, .Keyword_pub, "pub"); |
| 394 | const const_tok = try appendToken(c, .Keyword_const, "const"); | 407 | const const_tok = try appendToken(c, .Keyword_const, "const"); |
| 395 | | 408 | |
| 396 | const typedef_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, typedef_decl))); | 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 | const name_tok = try appendToken(c, .Identifier, typedef_name); | 410 | const name_tok = try appendToken(c, .Identifier, typedef_name); |
| 399 | const eq_tok = try appendToken(c, .Equal, "="); | 411 | const eq_tok = try appendToken(c, .Equal, "="); |
| 400 | | 412 | |
| ... | @@ -429,12 +441,9 @@ fn resolveTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl) Err | ... | @@ -429,12 +441,9 @@ fn resolveTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl) Err |
| 429 | } | 441 | } |
| 430 | | 442 | |
| 431 | fn resolveRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!void { | 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 | const rp = makeRestorePoint(c); | 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 | const bare_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, record_decl))); | 447 | const bare_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, record_decl))); |
| 439 | | 448 | |
| 440 | const container_kind_name = if (ZigClangRecordDecl_isUnion(record_decl)) | 449 | const container_kind_name = if (ZigClangRecordDecl_isUnion(record_decl)) |
| ... | @@ -447,8 +456,10 @@ fn resolveRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error! | ... | @@ -447,8 +456,10 @@ fn resolveRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error! |
| 447 | if (ZigClangRecordDecl_isAnonymousStructOrUnion(record_decl) or bare_name.len == 0) | 456 | if (ZigClangRecordDecl_isAnonymousStructOrUnion(record_decl) or bare_name.len == 0) |
| 448 | return; | 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 | const name = try std.fmt.allocPrint(c.a(), "{}_{}", .{ container_kind_name, bare_name }); | 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 | const name_tok = try appendToken(c, .Identifier, name); | 463 | const name_tok = try appendToken(c, .Identifier, name); |
| 453 | | 464 | |
| 454 | const eq_tok = try appendToken(c, .Equal, "="); | 465 | const eq_tok = try appendToken(c, .Equal, "="); |
| ... | @@ -480,6 +491,36 @@ fn resolveRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error! | ... | @@ -480,6 +491,36 @@ fn resolveRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error! |
| 480 | }; | 491 | }; |
| 481 | | 492 | |
| 482 | try addTopLevelDecl(c, name, &node.base); | 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 | const ResultUsed = enum { | 526 | const ResultUsed = enum { |
| ... | @@ -1063,9 +1104,9 @@ fn transInitListExpr( | ... | @@ -1063,9 +1104,9 @@ fn transInitListExpr( |
| 1063 | } | 1104 | } |
| 1064 | | 1105 | |
| 1065 | const arr_type = ZigClangType_getAsArrayTypeUnsafe(qual_type); | 1106 | const arr_type = ZigClangType_getAsArrayTypeUnsafe(qual_type); |
| 1066 | const const_arr_ty = @ptrCast(*const ZigClangConstantArrayType, qual_type); | | |
| 1067 | const child_qt = ZigClangArrayType_getElementType(arr_type); | 1107 | const child_qt = ZigClangArrayType_getElementType(arr_type); |
| 1068 | const init_count = ZigClangInitListExpr_getNumInits(expr); | 1108 | const init_count = ZigClangInitListExpr_getNumInits(expr); |
| | 1109 | const const_arr_ty = @ptrCast(*const ZigClangConstantArrayType, qual_type); |
| 1069 | const size_ap_int = ZigClangConstantArrayType_getSize(const_arr_ty); | 1110 | const size_ap_int = ZigClangConstantArrayType_getSize(const_arr_ty); |
| 1070 | const all_count = ZigClangAPInt_getLimitedValue(size_ap_int, std.math.maxInt(usize)); | 1111 | const all_count = ZigClangAPInt_getLimitedValue(size_ap_int, std.math.maxInt(usize)); |
| 1071 | const leftover_count = all_count - init_count; | 1112 | const leftover_count = all_count - init_count; |
| ... | @@ -1270,6 +1311,7 @@ fn maybeSuppressResult( | ... | @@ -1270,6 +1311,7 @@ fn maybeSuppressResult( |
| 1270 | | 1311 | |
| 1271 | 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 { |
| 1272 | 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, {}); |
| 1273 | } | 1315 | } |
| 1274 | | 1316 | |
| 1275 | 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 { |
| ... | @@ -1316,7 +1358,7 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) TypeErro | ... | @@ -1316,7 +1358,7 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) TypeErro |
| 1316 | .init_arg_expr = .None, | 1358 | .init_arg_expr = .None, |
| 1317 | .fields_and_decls = ast.Node.ContainerDecl.DeclList.init(c.a()), | 1359 | .fields_and_decls = ast.Node.ContainerDecl.DeclList.init(c.a()), |
| 1318 | .lbrace_token = lbrace_token, | 1360 | .lbrace_token = lbrace_token, |
| 1319 | .rbrace_token = undefined, // TODO | 1361 | .rbrace_token = undefined, |
| 1320 | }; | 1362 | }; |
| 1321 | | 1363 | |
| 1322 | var it = ZigClangRecordDecl_field_begin(record_def); | 1364 | var it = ZigClangRecordDecl_field_begin(record_def); |
| ... | @@ -1855,17 +1897,14 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour | ... | @@ -1855,17 +1897,14 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour |
| 1855 | const record_ty = @ptrCast(*const ZigClangRecordType, ty); | 1897 | const record_ty = @ptrCast(*const ZigClangRecordType, ty); |
| 1856 | | 1898 | |
| 1857 | const record_decl = ZigClangRecordType_getDecl(record_ty); | 1899 | const record_decl = ZigClangRecordType_getDecl(record_ty); |
| 1858 | if (rp.c.decl_table.get(@ptrToInt(ZigClangRecordDecl_getCanonicalDecl(record_decl)))) |kv| | 1900 | if (try getContainerName(rp.c, record_decl)) |name| |
| 1859 | return appendIdentifier(rp.c, kv.value) | 1901 | return appendIdentifier(rp.c, name) |
| 1860 | else | 1902 | else |
| 1861 | return transRecordDecl(rp.c, record_decl); | 1903 | return transRecordDecl(rp.c, record_decl); |
| 1862 | }, | 1904 | }, |
| 1863 | .Elaborated => { | 1905 | .Elaborated => { |
| 1864 | const elaborated_ty = @ptrCast(*const ZigClangElaboratedType, ty); | 1906 | const elaborated_ty = @ptrCast(*const ZigClangElaboratedType, ty); |
| 1865 | switch (ZigClangElaboratedType_getKeyword(elaborated_ty)) { | 1907 | return transQualType(rp, ZigClangElaboratedType_getNamedType(elaborated_ty), source_loc); |
| 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 | } | | |
| 1869 | }, | 1908 | }, |
| 1870 | else => { | 1909 | else => { |
| 1871 | const type_name = rp.c.str(ZigClangType_getTypeClassName(ty)); | 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,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 | fn isCVoid(qt: ZigClangQualType) bool { | 1934 | fn isCVoid(qt: ZigClangQualType) bool { |
| 1878 | const ty = ZigClangQualType_getTypePtr(qt); | 1935 | const ty = ZigClangQualType_getTypePtr(qt); |
| 1879 | if (ZigClangType_getTypeClass(ty) == .Builtin) { | 1936 | if (ZigClangType_getTypeClass(ty) == .Builtin) { |