| ... | @@ -3,14 +3,14 @@ | ... | @@ -3,14 +3,14 @@ |
| 3 | | 3 | |
| 4 | const std = @import("std"); | 4 | const std = @import("std"); |
| 5 | const assert = std.debug.assert; | 5 | const assert = std.debug.assert; |
| 6 | const ast = std.zig.ast; | | |
| 7 | const Token = std.zig.Token; | | |
| 8 | const clang = @import("clang.zig"); | 6 | const clang = @import("clang.zig"); |
| 9 | const ctok = std.c.tokenizer; | 7 | const ctok = std.c.tokenizer; |
| 10 | const CToken = std.c.Token; | 8 | const CToken = std.c.Token; |
| 11 | const mem = std.mem; | 9 | const mem = std.mem; |
| 12 | const math = std.math; | 10 | const math = std.math; |
| 13 | const Type = @import("type.zig").Type; | 11 | const Type = @import("type.zig").Type; |
| | 12 | const ast = @import("translate_c/ast.zig"); |
| | 13 | const Node = ast.Node; |
| 14 | | 14 | |
| 15 | const CallingConvention = std.builtin.CallingConvention; | 15 | const CallingConvention = std.builtin.CallingConvention; |
| 16 | | 16 | |
| ... | @@ -348,47 +348,6 @@ pub const Context = struct { | ... | @@ -348,47 +348,6 @@ pub const Context = struct { |
| 348 | } | 348 | } |
| 349 | }; | 349 | }; |
| 350 | | 350 | |
| 351 | fn addCBuiltinsNamespace(c: *Context) Error!void { | | |
| 352 | // pub usingnamespace @import("std").c.builtins; | | |
| 353 | const pub_tok = try appendToken(c, .Keyword_pub, "pub"); | | |
| 354 | const use_tok = try appendToken(c, .Keyword_usingnamespace, "usingnamespace"); | | |
| 355 | const import_tok = try appendToken(c, .Builtin, "@import"); | | |
| 356 | const lparen_tok = try appendToken(c, .LParen, "("); | | |
| 357 | const std_tok = try appendToken(c, .StringLiteral, "\"std\""); | | |
| 358 | const rparen_tok = try appendToken(c, .RParen, ")"); | | |
| 359 | | | |
| 360 | const std_node = try c.arena.create(ast.Node.OneToken); | | |
| 361 | std_node.* = .{ | | |
| 362 | .base = .{ .tag = .StringLiteral }, | | |
| 363 | .token = std_tok, | | |
| 364 | }; | | |
| 365 | | | |
| 366 | const call_node = try ast.Node.BuiltinCall.alloc(c.arena, 1); | | |
| 367 | call_node.* = .{ | | |
| 368 | .builtin_token = import_tok, | | |
| 369 | .params_len = 1, | | |
| 370 | .rparen_token = rparen_tok, | | |
| 371 | }; | | |
| 372 | call_node.params()[0] = &std_node.base; | | |
| 373 | | | |
| 374 | var access_chain = &call_node.base; | | |
| 375 | access_chain = try transCreateNodeFieldAccess(c, access_chain, "c"); | | |
| 376 | access_chain = try transCreateNodeFieldAccess(c, access_chain, "builtins"); | | |
| 377 | | | |
| 378 | const semi_tok = try appendToken(c, .Semicolon, ";"); | | |
| 379 | | | |
| 380 | const bytes = try c.gpa.alignedAlloc(u8, @alignOf(ast.Node.Use), @sizeOf(ast.Node.Use)); | | |
| 381 | const using_node = @ptrCast(*ast.Node.Use, bytes.ptr); | | |
| 382 | using_node.* = .{ | | |
| 383 | .doc_comments = null, | | |
| 384 | .visib_token = pub_tok, | | |
| 385 | .use_token = use_tok, | | |
| 386 | .expr = access_chain, | | |
| 387 | .semicolon_token = semi_tok, | | |
| 388 | }; | | |
| 389 | try c.root_decls.append(c.gpa, &using_node.base); | | |
| 390 | } | | |
| 391 | | | |
| 392 | pub fn translate( | 351 | pub fn translate( |
| 393 | gpa: *mem.Allocator, | 352 | gpa: *mem.Allocator, |
| 394 | args_begin: [*]?[*]const u8, | 353 | args_begin: [*]?[*]const u8, |
| ... | @@ -446,7 +405,7 @@ pub fn translate( | ... | @@ -446,7 +405,7 @@ pub fn translate( |
| 446 | context.opaque_demotes.deinit(gpa); | 405 | context.opaque_demotes.deinit(gpa); |
| 447 | } | 406 | } |
| 448 | | 407 | |
| 449 | try addCBuiltinsNamespace(&context); | 408 | _ = try Node.usingnamespace_builtins.init(); |
| 450 | | 409 | |
| 451 | try prepopulateGlobalNameTable(ast_unit, &context); | 410 | try prepopulateGlobalNameTable(ast_unit, &context); |
| 452 | | 411 | |
| ... | @@ -1318,26 +1277,6 @@ fn transEnumDecl(c: *Context, enum_decl: *const clang.EnumDecl) Error!?*ast.Node | ... | @@ -1318,26 +1277,6 @@ fn transEnumDecl(c: *Context, enum_decl: *const clang.EnumDecl) Error!?*ast.Node |
| 1318 | return transCreateNodeIdentifier(c, name); | 1277 | return transCreateNodeIdentifier(c, name); |
| 1319 | } | 1278 | } |
| 1320 | | 1279 | |
| 1321 | fn createAlias(c: *Context, alias: anytype) !void { | | |
| 1322 | const visib_tok = try appendToken(c, .Keyword_pub, "pub"); | | |
| 1323 | const mut_tok = try appendToken(c, .Keyword_const, "const"); | | |
| 1324 | const name_tok = try appendIdentifier(c, alias.alias); | | |
| 1325 | const eq_token = try appendToken(c, .Equal, "="); | | |
| 1326 | const init_node = try transCreateNodeIdentifier(c, alias.name); | | |
| 1327 | const semicolon_token = try appendToken(c, .Semicolon, ";"); | | |
| 1328 | | | |
| 1329 | const node = try ast.Node.VarDecl.create(c.arena, .{ | | |
| 1330 | .name_token = name_tok, | | |
| 1331 | .mut_token = mut_tok, | | |
| 1332 | .semicolon_token = semicolon_token, | | |
| 1333 | }, .{ | | |
| 1334 | .visib_token = visib_tok, | | |
| 1335 | .eq_token = eq_token, | | |
| 1336 | .init_node = init_node, | | |
| 1337 | }); | | |
| 1338 | return addTopLevelDecl(c, alias.alias, &node.base); | | |
| 1339 | } | | |
| 1340 | | | |
| 1341 | const ResultUsed = enum { | 1280 | const ResultUsed = enum { |
| 1342 | used, | 1281 | used, |
| 1343 | unused, | 1282 | unused, |
| ... | @@ -1349,78 +1288,63 @@ const LRValue = enum { | ... | @@ -1349,78 +1288,63 @@ const LRValue = enum { |
| 1349 | }; | 1288 | }; |
| 1350 | | 1289 | |
| 1351 | fn transStmt( | 1290 | fn transStmt( |
| 1352 | rp: RestorePoint, | 1291 | c: *Context, |
| 1353 | scope: *Scope, | 1292 | scope: *Scope, |
| 1354 | stmt: *const clang.Stmt, | 1293 | stmt: *const clang.Stmt, |
| 1355 | result_used: ResultUsed, | 1294 | result_used: ResultUsed, |
| 1356 | lrvalue: LRValue, | 1295 | lrvalue: LRValue, |
| 1357 | ) TransError!*ast.Node { | 1296 | ) TransError!Node { |
| 1358 | const sc = stmt.getStmtClass(); | 1297 | const sc = stmt.getStmtClass(); |
| 1359 | switch (sc) { | 1298 | switch (sc) { |
| 1360 | .BinaryOperatorClass => return transBinaryOperator(rp, scope, @ptrCast(*const clang.BinaryOperator, stmt), result_used), | 1299 | .BinaryOperatorClass => return transBinaryOperator(c, scope, @ptrCast(*const clang.BinaryOperator, stmt), result_used), |
| 1361 | .CompoundStmtClass => return transCompoundStmt(rp, scope, @ptrCast(*const clang.CompoundStmt, stmt)), | 1300 | .CompoundStmtClass => return transCompoundStmt(c, scope, @ptrCast(*const clang.CompoundStmt, stmt)), |
| 1362 | .CStyleCastExprClass => return transCStyleCastExprClass(rp, scope, @ptrCast(*const clang.CStyleCastExpr, stmt), result_used, lrvalue), | 1301 | .CStyleCastExprClass => return transCStyleCastExprClass(c, scope, @ptrCast(*const clang.CStyleCastExpr, stmt), result_used, lrvalue), |
| 1363 | .DeclStmtClass => return transDeclStmt(rp, scope, @ptrCast(*const clang.DeclStmt, stmt)), | 1302 | .DeclStmtClass => return transDeclStmt(c, scope, @ptrCast(*const clang.DeclStmt, stmt)), |
| 1364 | .DeclRefExprClass => return transDeclRefExpr(rp, scope, @ptrCast(*const clang.DeclRefExpr, stmt), lrvalue), | 1303 | .DeclRefExprClass => return transDeclRefExpr(c, scope, @ptrCast(*const clang.DeclRefExpr, stmt), lrvalue), |
| 1365 | .ImplicitCastExprClass => return transImplicitCastExpr(rp, scope, @ptrCast(*const clang.ImplicitCastExpr, stmt), result_used), | 1304 | .ImplicitCastExprClass => return transImplicitCastExpr(c, scope, @ptrCast(*const clang.ImplicitCastExpr, stmt), result_used), |
| 1366 | .IntegerLiteralClass => return transIntegerLiteral(rp, scope, @ptrCast(*const clang.IntegerLiteral, stmt), result_used, .with_as), | 1305 | .IntegerLiteralClass => return transIntegerLiteral(c, scope, @ptrCast(*const clang.IntegerLiteral, stmt), result_used, .with_as), |
| 1367 | .ReturnStmtClass => return transReturnStmt(rp, scope, @ptrCast(*const clang.ReturnStmt, stmt)), | 1306 | .ReturnStmtClass => return transReturnStmt(c, scope, @ptrCast(*const clang.ReturnStmt, stmt)), |
| 1368 | .StringLiteralClass => return transStringLiteral(rp, scope, @ptrCast(*const clang.StringLiteral, stmt), result_used), | 1307 | .StringLiteralClass => return transStringLiteral(c, scope, @ptrCast(*const clang.StringLiteral, stmt), result_used), |
| 1369 | .ParenExprClass => { | 1308 | .ParenExprClass => { |
| 1370 | const expr = try transExpr(rp, scope, @ptrCast(*const clang.ParenExpr, stmt).getSubExpr(), .used, lrvalue); | 1309 | const expr = try transExpr(c, scope, @ptrCast(*const clang.ParenExpr, stmt).getSubExpr(), .used, lrvalue); |
| 1371 | if (expr.tag == .GroupedExpression) return maybeSuppressResult(rp, scope, result_used, expr); | 1310 | return maybeSuppressResult(c, scope, result_used, expr); |
| 1372 | const node = try rp.c.arena.create(ast.Node.GroupedExpression); | 1311 | }, |
| 1373 | node.* = .{ | 1312 | .InitListExprClass => return transInitListExpr(c, scope, @ptrCast(*const clang.InitListExpr, stmt), result_used), |
| 1374 | .lparen = try appendToken(rp.c, .LParen, "("), | 1313 | .ImplicitValueInitExprClass => return transImplicitValueInitExpr(c, scope, @ptrCast(*const clang.Expr, stmt), result_used), |
| 1375 | .expr = expr, | 1314 | .IfStmtClass => return transIfStmt(c, scope, @ptrCast(*const clang.IfStmt, stmt)), |
| 1376 | .rparen = try appendToken(rp.c, .RParen, ")"), | 1315 | .WhileStmtClass => return transWhileLoop(c, scope, @ptrCast(*const clang.WhileStmt, stmt)), |
| 1377 | }; | 1316 | .DoStmtClass => return transDoWhileLoop(c, scope, @ptrCast(*const clang.DoStmt, stmt)), |
| 1378 | return maybeSuppressResult(rp, scope, result_used, &node.base); | | |
| 1379 | }, | | |
| 1380 | .InitListExprClass => return transInitListExpr(rp, scope, @ptrCast(*const clang.InitListExpr, stmt), result_used), | | |
| 1381 | .ImplicitValueInitExprClass => return transImplicitValueInitExpr(rp, scope, @ptrCast(*const clang.Expr, stmt), result_used), | | |
| 1382 | .IfStmtClass => return transIfStmt(rp, scope, @ptrCast(*const clang.IfStmt, stmt)), | | |
| 1383 | .WhileStmtClass => return transWhileLoop(rp, scope, @ptrCast(*const clang.WhileStmt, stmt)), | | |
| 1384 | .DoStmtClass => return transDoWhileLoop(rp, scope, @ptrCast(*const clang.DoStmt, stmt)), | | |
| 1385 | .NullStmtClass => { | 1317 | .NullStmtClass => { |
| 1386 | const block = try rp.c.createBlock(0); | 1318 | return Node.empty_block.init(); |
| 1387 | block.rbrace = try appendToken(rp.c, .RBrace, "}"); | 1319 | }, |
| 1388 | return &block.base; | 1320 | .ContinueStmtClass => return try transCreateNodeContinue(c), |
| 1389 | }, | 1321 | .BreakStmtClass => return transBreak(c, scope), |
| 1390 | .ContinueStmtClass => return try transCreateNodeContinue(rp.c), | 1322 | .ForStmtClass => return transForLoop(c, scope, @ptrCast(*const clang.ForStmt, stmt)), |
| 1391 | .BreakStmtClass => return transBreak(rp, scope), | 1323 | .FloatingLiteralClass => return transFloatingLiteral(c, scope, @ptrCast(*const clang.FloatingLiteral, stmt), result_used), |
| 1392 | .ForStmtClass => return transForLoop(rp, scope, @ptrCast(*const clang.ForStmt, stmt)), | | |
| 1393 | .FloatingLiteralClass => return transFloatingLiteral(rp, scope, @ptrCast(*const clang.FloatingLiteral, stmt), result_used), | | |
| 1394 | .ConditionalOperatorClass => { | 1324 | .ConditionalOperatorClass => { |
| 1395 | return transConditionalOperator(rp, scope, @ptrCast(*const clang.ConditionalOperator, stmt), result_used); | 1325 | return transConditionalOperator(c, scope, @ptrCast(*const clang.ConditionalOperator, stmt), result_used); |
| 1396 | }, | 1326 | }, |
| 1397 | .BinaryConditionalOperatorClass => { | 1327 | .BinaryConditionalOperatorClass => { |
| 1398 | return transBinaryConditionalOperator(rp, scope, @ptrCast(*const clang.BinaryConditionalOperator, stmt), result_used); | 1328 | return transBinaryConditionalOperator(c, scope, @ptrCast(*const clang.BinaryConditionalOperator, stmt), result_used); |
| 1399 | }, | 1329 | }, |
| 1400 | .SwitchStmtClass => return transSwitch(rp, scope, @ptrCast(*const clang.SwitchStmt, stmt)), | 1330 | .SwitchStmtClass => return transSwitch(c, scope, @ptrCast(*const clang.SwitchStmt, stmt)), |
| 1401 | .CaseStmtClass => return transCase(rp, scope, @ptrCast(*const clang.CaseStmt, stmt)), | 1331 | .CaseStmtClass => return transCase(c, scope, @ptrCast(*const clang.CaseStmt, stmt)), |
| 1402 | .DefaultStmtClass => return transDefault(rp, scope, @ptrCast(*const clang.DefaultStmt, stmt)), | 1332 | .DefaultStmtClass => return transDefault(c, scope, @ptrCast(*const clang.DefaultStmt, stmt)), |
| 1403 | .ConstantExprClass => return transConstantExpr(rp, scope, @ptrCast(*const clang.Expr, stmt), result_used), | 1333 | .ConstantExprClass => return transConstantExpr(c, scope, @ptrCast(*const clang.Expr, stmt), result_used), |
| 1404 | .PredefinedExprClass => return transPredefinedExpr(rp, scope, @ptrCast(*const clang.PredefinedExpr, stmt), result_used), | 1334 | .PredefinedExprClass => return transPredefinedExpr(c, scope, @ptrCast(*const clang.PredefinedExpr, stmt), result_used), |
| 1405 | .CharacterLiteralClass => return transCharLiteral(rp, scope, @ptrCast(*const clang.CharacterLiteral, stmt), result_used, .with_as), | 1335 | .CharacterLiteralClass => return transCharLiteral(c, scope, @ptrCast(*const clang.CharacterLiteral, stmt), result_used, .with_as), |
| 1406 | .StmtExprClass => return transStmtExpr(rp, scope, @ptrCast(*const clang.StmtExpr, stmt), result_used), | 1336 | .StmtExprClass => return transStmtExpr(c, scope, @ptrCast(*const clang.StmtExpr, stmt), result_used), |
| 1407 | .MemberExprClass => return transMemberExpr(rp, scope, @ptrCast(*const clang.MemberExpr, stmt), result_used), | 1337 | .MemberExprClass => return transMemberExpr(c, scope, @ptrCast(*const clang.MemberExpr, stmt), result_used), |
| 1408 | .ArraySubscriptExprClass => return transArrayAccess(rp, scope, @ptrCast(*const clang.ArraySubscriptExpr, stmt), result_used), | 1338 | .ArraySubscriptExprClass => return transArrayAccess(c, scope, @ptrCast(*const clang.ArraySubscriptExpr, stmt), result_used), |
| 1409 | .CallExprClass => return transCallExpr(rp, scope, @ptrCast(*const clang.CallExpr, stmt), result_used), | 1339 | .CallExprClass => return transCallExpr(c, scope, @ptrCast(*const clang.CallExpr, stmt), result_used), |
| 1410 | .UnaryExprOrTypeTraitExprClass => return transUnaryExprOrTypeTraitExpr(rp, scope, @ptrCast(*const clang.UnaryExprOrTypeTraitExpr, stmt), result_used), | 1340 | .UnaryExprOrTypeTraitExprClass => return transUnaryExprOrTypeTraitExpr(c, scope, @ptrCast(*const clang.UnaryExprOrTypeTraitExpr, stmt), result_used), |
| 1411 | .UnaryOperatorClass => return transUnaryOperator(rp, scope, @ptrCast(*const clang.UnaryOperator, stmt), result_used), | 1341 | .UnaryOperatorClass => return transUnaryOperator(c, scope, @ptrCast(*const clang.UnaryOperator, stmt), result_used), |
| 1412 | .CompoundAssignOperatorClass => return transCompoundAssignOperator(rp, scope, @ptrCast(*const clang.CompoundAssignOperator, stmt), result_used), | 1342 | .CompoundAssignOperatorClass => return transCompoundAssignOperator(c, scope, @ptrCast(*const clang.CompoundAssignOperator, stmt), result_used), |
| 1413 | .OpaqueValueExprClass => { | 1343 | .OpaqueValueExprClass => { |
| 1414 | const source_expr = @ptrCast(*const clang.OpaqueValueExpr, stmt).getSourceExpr().?; | 1344 | const source_expr = @ptrCast(*const clang.OpaqueValueExpr, stmt).getSourceExpr().?; |
| 1415 | const expr = try transExpr(rp, scope, source_expr, .used, lrvalue); | 1345 | const expr = try transExpr(c, scope, source_expr, .used, lrvalue); |
| 1416 | if (expr.tag == .GroupedExpression) return maybeSuppressResult(rp, scope, result_used, expr); | 1346 | return maybeSuppressResult(c, scope, result_used, expr); |
| 1417 | const node = try rp.c.arena.create(ast.Node.GroupedExpression); | 1347 | const node = try c.arena.create(Node.GroupedExpression); |
| 1418 | node.* = .{ | | |
| 1419 | .lparen = try appendToken(rp.c, .LParen, "("), | | |
| 1420 | .expr = expr, | | |
| 1421 | .rparen = try appendToken(rp.c, .RParen, ")"), | | |
| 1422 | }; | | |
| 1423 | return maybeSuppressResult(rp, scope, result_used, &node.base); | | |
| 1424 | }, | 1348 | }, |
| 1425 | else => { | 1349 | else => { |
| 1426 | return revertAndWarn( | 1350 | return revertAndWarn( |
| ... | @@ -1435,175 +1359,139 @@ fn transStmt( | ... | @@ -1435,175 +1359,139 @@ fn transStmt( |
| 1435 | } | 1359 | } |
| 1436 | | 1360 | |
| 1437 | fn transBinaryOperator( | 1361 | fn transBinaryOperator( |
| 1438 | rp: RestorePoint, | 1362 | c: *Context, |
| 1439 | scope: *Scope, | 1363 | scope: *Scope, |
| 1440 | stmt: *const clang.BinaryOperator, | 1364 | stmt: *const clang.BinaryOperator, |
| 1441 | result_used: ResultUsed, | 1365 | result_used: ResultUsed, |
| 1442 | ) TransError!*ast.Node { | 1366 | ) TransError!Node { |
| 1443 | const op = stmt.getOpcode(); | 1367 | const op = stmt.getOpcode(); |
| 1444 | const qt = stmt.getType(); | 1368 | const qt = stmt.getType(); |
| 1445 | var op_token: ast.TokenIndex = undefined; | | |
| 1446 | var op_id: ast.Node.Tag = undefined; | | |
| 1447 | switch (op) { | 1369 | switch (op) { |
| 1448 | .Assign => return try transCreateNodeAssign(rp, scope, result_used, stmt.getLHS(), stmt.getRHS()), | 1370 | .Assign => return try transCreateNodeAssign(c, scope, result_used, stmt.getLHS(), stmt.getRHS()), |
| 1449 | .Comma => { | 1371 | .Comma => { |
| 1450 | var block_scope = try Scope.Block.init(rp.c, scope, true); | 1372 | var block_scope = try Scope.Block.init(rp.c, scope, true); |
| 1451 | const lparen = try appendToken(rp.c, .LParen, "("); | 1373 | defer block_scope.deinit(); |
| | 1374 | |
| 1452 | | 1375 | |
| 1453 | const lhs = try transExpr(rp, &block_scope.base, stmt.getLHS(), .unused, .r_value); | 1376 | const lhs = try transExpr(c, &block_scope.base, stmt.getLHS(), .unused, .r_value); |
| 1454 | try block_scope.statements.append(lhs); | 1377 | try block_scope.statements.append(lhs); |
| 1455 | | 1378 | |
| 1456 | const rhs = try transExpr(rp, &block_scope.base, stmt.getRHS(), .used, .r_value); | 1379 | const rhs = try transExpr(rp, &block_scope.base, stmt.getRHS(), .used, .r_value); |
| 1457 | _ = try appendToken(rp.c, .Semicolon, ";"); | 1380 | const break_node = try Node.break_val.create(c.arena, .{ |
| 1458 | const break_node = try transCreateNodeBreak(rp.c, block_scope.label, rhs); | 1381 | .label = block_scope.label, |
| 1459 | try block_scope.statements.append(&break_node.base); | 1382 | .val = rhs, |
| | 1383 | }); |
| | 1384 | try block_scope.statements.append(break_node); |
| 1460 | const block_node = try block_scope.complete(rp.c); | 1385 | const block_node = try block_scope.complete(rp.c); |
| 1461 | const rparen = try appendToken(rp.c, .RParen, ")"); | 1386 | return maybeSuppressResult(rp, scope, result_used, block_node); |
| 1462 | const grouped_expr = try rp.c.arena.create(ast.Node.GroupedExpression); | | |
| 1463 | grouped_expr.* = .{ | | |
| 1464 | .lparen = lparen, | | |
| 1465 | .expr = block_node, | | |
| 1466 | .rparen = rparen, | | |
| 1467 | }; | | |
| 1468 | return maybeSuppressResult(rp, scope, result_used, &grouped_expr.base); | | |
| 1469 | }, | 1387 | }, |
| 1470 | .Div => { | 1388 | .Div => { |
| 1471 | if (cIsSignedInteger(qt)) { | 1389 | if (cIsSignedInteger(qt)) { |
| 1472 | // signed integer division uses @divTrunc | 1390 | // signed integer division uses @divTrunc |
| 1473 | const div_trunc_node = try rp.c.createBuiltinCall("@divTrunc", 2); | 1391 | const lhs = try transExpr(c, scope, stmt.getLHS(), .used, .l_value); |
| 1474 | div_trunc_node.params()[0] = try transExpr(rp, scope, stmt.getLHS(), .used, .l_value); | 1392 | const rhs = try transExpr(c, scope, stmt.getRHS(), .used, .r_value); |
| 1475 | _ = try appendToken(rp.c, .Comma, ","); | 1393 | const div_trunc = try Node.div_trunc.create(c.arena, .{ .lhs = lhs, .rhs = rhs}); |
| 1476 | const rhs = try transExpr(rp, scope, stmt.getRHS(), .used, .r_value); | 1394 | return maybeSuppressResult(c, scope, result_used, div_trunc); |
| 1477 | div_trunc_node.params()[1] = rhs; | | |
| 1478 | div_trunc_node.rparen_token = try appendToken(rp.c, .RParen, ")"); | | |
| 1479 | return maybeSuppressResult(rp, scope, result_used, &div_trunc_node.base); | | |
| 1480 | } | 1395 | } |
| 1481 | }, | 1396 | }, |
| 1482 | .Rem => { | 1397 | .Rem => { |
| 1483 | if (cIsSignedInteger(qt)) { | 1398 | if (cIsSignedInteger(qt)) { |
| 1484 | // signed integer division uses @rem | 1399 | // signed integer division uses @rem |
| 1485 | const rem_node = try rp.c.createBuiltinCall("@rem", 2); | 1400 | const lhs = try transExpr(c, scope, stmt.getLHS(), .used, .l_value); |
| 1486 | rem_node.params()[0] = try transExpr(rp, scope, stmt.getLHS(), .used, .l_value); | 1401 | const rhs = try transExpr(c, scope, stmt.getRHS(), .used, .r_value); |
| 1487 | _ = try appendToken(rp.c, .Comma, ","); | 1402 | const rem = try Node.rem.create(c.arena, .{ .lhs = lhs, .rhs = rhs}); |
| 1488 | const rhs = try transExpr(rp, scope, stmt.getRHS(), .used, .r_value); | 1403 | return maybeSuppressResult(c, scope, result_used, rem); |
| 1489 | rem_node.params()[1] = rhs; | | |
| 1490 | rem_node.rparen_token = try appendToken(rp.c, .RParen, ")"); | | |
| 1491 | return maybeSuppressResult(rp, scope, result_used, &rem_node.base); | | |
| 1492 | } | 1404 | } |
| 1493 | }, | 1405 | }, |
| 1494 | .Shl => { | 1406 | .Shl => { |
| 1495 | const node = try transCreateNodeShiftOp(rp, scope, stmt, .BitShiftLeft, .AngleBracketAngleBracketLeft, "<<"); | 1407 | const node = try transCreateNodeShiftOp(c, scope, stmt, .shl); |
| 1496 | return maybeSuppressResult(rp, scope, result_used, node); | 1408 | return maybeSuppressResult(c, scope, result_used, node); |
| 1497 | }, | 1409 | }, |
| 1498 | .Shr => { | 1410 | .Shr => { |
| 1499 | const node = try transCreateNodeShiftOp(rp, scope, stmt, .BitShiftRight, .AngleBracketAngleBracketRight, ">>"); | 1411 | const node = try transCreateNodeShiftOp(c, scope, stmt, .shr); |
| 1500 | return maybeSuppressResult(rp, scope, result_used, node); | 1412 | return maybeSuppressResult(c, scope, result_used, node); |
| 1501 | }, | | |
| 1502 | .LAnd => { | | |
| 1503 | const node = try transCreateNodeBoolInfixOp(rp, scope, stmt, .BoolAnd, result_used, true); | | |
| 1504 | return maybeSuppressResult(rp, scope, result_used, node); | | |
| 1505 | }, | | |
| 1506 | .LOr => { | | |
| 1507 | const node = try transCreateNodeBoolInfixOp(rp, scope, stmt, .BoolOr, result_used, true); | | |
| 1508 | return maybeSuppressResult(rp, scope, result_used, node); | | |
| 1509 | }, | 1413 | }, |
| 1510 | else => {}, | 1414 | else => {}, |
| 1511 | } | 1415 | } |
| 1512 | const lhs_node = try transExpr(rp, scope, stmt.getLHS(), .used, .l_value); | 1416 | var op_id: Node.Tag = undefined; |
| 1513 | switch (op) { | 1417 | switch (op) { |
| 1514 | .Add => { | 1418 | .Add => { |
| 1515 | if (cIsUnsignedInteger(qt)) { | 1419 | if (cIsUnsignedInteger(qt)) { |
| 1516 | op_token = try appendToken(rp.c, .PlusPercent, "+%"); | 1420 | op_id = .add_wrap; |
| 1517 | op_id = .AddWrap; | | |
| 1518 | } else { | 1421 | } else { |
| 1519 | op_token = try appendToken(rp.c, .Plus, "+"); | 1422 | op_id = .add; |
| 1520 | op_id = .Add; | | |
| 1521 | } | 1423 | } |
| 1522 | }, | 1424 | }, |
| 1523 | .Sub => { | 1425 | .Sub => { |
| 1524 | if (cIsUnsignedInteger(qt)) { | 1426 | if (cIsUnsignedInteger(qt)) { |
| 1525 | op_token = try appendToken(rp.c, .MinusPercent, "-%"); | 1427 | op_id = .sub_wrap; |
| 1526 | op_id = .SubWrap; | | |
| 1527 | } else { | 1428 | } else { |
| 1528 | op_token = try appendToken(rp.c, .Minus, "-"); | 1429 | op_id = .sub; |
| 1529 | op_id = .Sub; | | |
| 1530 | } | 1430 | } |
| 1531 | }, | 1431 | }, |
| 1532 | .Mul => { | 1432 | .Mul => { |
| 1533 | if (cIsUnsignedInteger(qt)) { | 1433 | if (cIsUnsignedInteger(qt)) { |
| 1534 | op_token = try appendToken(rp.c, .AsteriskPercent, "*%"); | 1434 | op_id = .mul_wrap; |
| 1535 | op_id = .MulWrap; | | |
| 1536 | } else { | 1435 | } else { |
| 1537 | op_token = try appendToken(rp.c, .Asterisk, "*"); | 1436 | op_id = .mul; |
| 1538 | op_id = .Mul; | | |
| 1539 | } | 1437 | } |
| 1540 | }, | 1438 | }, |
| 1541 | .Div => { | 1439 | .Div => { |
| 1542 | // unsigned/float division uses the operator | 1440 | // unsigned/float division uses the operator |
| 1543 | op_id = .Div; | 1441 | op_id = .div; |
| 1544 | op_token = try appendToken(rp.c, .Slash, "/"); | | |
| 1545 | }, | 1442 | }, |
| 1546 | .Rem => { | 1443 | .Rem => { |
| 1547 | // unsigned/float division uses the operator | 1444 | // unsigned/float division uses the operator |
| 1548 | op_id = .Mod; | 1445 | op_id = .mod; |
| 1549 | op_token = try appendToken(rp.c, .Percent, "%"); | | |
| 1550 | }, | 1446 | }, |
| 1551 | .LT => { | 1447 | .LT => { |
| 1552 | op_id = .LessThan; | 1448 | op_id = .less_than; |
| 1553 | op_token = try appendToken(rp.c, .AngleBracketLeft, "<"); | | |
| 1554 | }, | 1449 | }, |
| 1555 | .GT => { | 1450 | .GT => { |
| 1556 | op_id = .GreaterThan; | 1451 | op_id = .greater_than; |
| 1557 | op_token = try appendToken(rp.c, .AngleBracketRight, ">"); | | |
| 1558 | }, | 1452 | }, |
| 1559 | .LE => { | 1453 | .LE => { |
| 1560 | op_id = .LessOrEqual; | 1454 | op_id = .less_than_equal; |
| 1561 | op_token = try appendToken(rp.c, .AngleBracketLeftEqual, "<="); | | |
| 1562 | }, | 1455 | }, |
| 1563 | .GE => { | 1456 | .GE => { |
| 1564 | op_id = .GreaterOrEqual; | 1457 | op_id = .greater_than_equal; |
| 1565 | op_token = try appendToken(rp.c, .AngleBracketRightEqual, ">="); | | |
| 1566 | }, | 1458 | }, |
| 1567 | .EQ => { | 1459 | .EQ => { |
| 1568 | op_id = .EqualEqual; | 1460 | op_id = .equal; |
| 1569 | op_token = try appendToken(rp.c, .EqualEqual, "=="); | | |
| 1570 | }, | 1461 | }, |
| 1571 | .NE => { | 1462 | .NE => { |
| 1572 | op_id = .BangEqual; | 1463 | op_id = .not_equal; |
| 1573 | op_token = try appendToken(rp.c, .BangEqual, "!="); | | |
| 1574 | }, | 1464 | }, |
| 1575 | .And => { | 1465 | .And => { |
| 1576 | op_id = .BitAnd; | 1466 | op_id = .bit_and; |
| 1577 | op_token = try appendToken(rp.c, .Ampersand, "&"); | | |
| 1578 | }, | 1467 | }, |
| 1579 | .Xor => { | 1468 | .Xor => { |
| 1580 | op_id = .BitXor; | 1469 | op_id = .bit_xor; |
| 1581 | op_token = try appendToken(rp.c, .Caret, "^"); | | |
| 1582 | }, | 1470 | }, |
| 1583 | .Or => { | 1471 | .Or => { |
| 1584 | op_id = .BitOr; | 1472 | op_id = .bit_or; |
| 1585 | op_token = try appendToken(rp.c, .Pipe, "|"); | 1473 | }, |
| | 1474 | .LAnd => { |
| | 1475 | op_id = .@"and"; |
| | 1476 | }, |
| | 1477 | .LOr => { |
| | 1478 | op_id = .@"or"; |
| 1586 | }, | 1479 | }, |
| 1587 | else => unreachable, | 1480 | else => unreachable, |
| 1588 | } | 1481 | } |
| 1589 | | 1482 | |
| 1590 | const rhs_node = try transExpr(rp, scope, stmt.getRHS(), .used, .r_value); | 1483 | const lhs = try transExpr(c, scope, stmt.getLHS(), .used, .l_value); |
| 1591 | | 1484 | const rhs = try transExpr(c, scope, stmt.getRHS(), .used, .r_value); |
| 1592 | const lhs = if (isBoolRes(lhs_node)) init: { | | |
| 1593 | const cast_node = try rp.c.createBuiltinCall("@boolToInt", 1); | | |
| 1594 | cast_node.params()[0] = lhs_node; | | |
| 1595 | cast_node.rparen_token = try appendToken(rp.c, .RParen, ")"); | | |
| 1596 | break :init &cast_node.base; | | |
| 1597 | } else lhs_node; | | |
| 1598 | | | |
| 1599 | const rhs = if (isBoolRes(rhs_node)) init: { | | |
| 1600 | const cast_node = try rp.c.createBuiltinCall("@boolToInt", 1); | | |
| 1601 | cast_node.params()[0] = rhs_node; | | |
| 1602 | cast_node.rparen_token = try appendToken(rp.c, .RParen, ")"); | | |
| 1603 | break :init &cast_node.base; | | |
| 1604 | } else rhs_node; | | |
| 1605 | | 1485 | |
| 1606 | return transCreateNodeInfixOp(rp, scope, lhs, op_id, op_token, rhs, result_used, true); | 1486 | const payload = try c.arena.create(ast.Payload.BinOp); |
| | 1487 | payload.* = .{ |
| | 1488 | .base = .{ .tag = op_id }, |
| | 1489 | .data = .{ |
| | 1490 | .lhs = lhs, |
| | 1491 | .rhs = rhs, |
| | 1492 | }, |
| | 1493 | }; |
| | 1494 | return maybeSuppressResult(c, scope, used, &payload.base); |
| 1607 | } | 1495 | } |
| 1608 | | 1496 | |
| 1609 | fn transCompoundStmtInline( | 1497 | fn transCompoundStmtInline( |
| ... | @@ -2365,40 +2253,13 @@ fn transEnumToInt(c: *Context, enum_expr: *ast.Node) TypeError!*ast.Node { | ... | @@ -2365,40 +2253,13 @@ fn transEnumToInt(c: *Context, enum_expr: *ast.Node) TypeError!*ast.Node { |
| 2365 | } | 2253 | } |
| 2366 | | 2254 | |
| 2367 | fn transExpr( | 2255 | fn transExpr( |
| 2368 | rp: RestorePoint, | 2256 | c: *Context, |
| 2369 | scope: *Scope, | | |
| 2370 | expr: *const clang.Expr, | | |
| 2371 | used: ResultUsed, | | |
| 2372 | lrvalue: LRValue, | | |
| 2373 | ) TransError!*ast.Node { | | |
| 2374 | return transStmt(rp, scope, @ptrCast(*const clang.Stmt, expr), used, lrvalue); | | |
| 2375 | } | | |
| 2376 | | | |
| 2377 | /// Same as `transExpr` but with the knowledge that the operand will be type coerced, and therefore | | |
| 2378 | /// an `@as` would be redundant. This is used to prevent redundant `@as` in integer literals. | | |
| 2379 | fn transExprCoercing( | | |
| 2380 | rp: RestorePoint, | | |
| 2381 | scope: *Scope, | 2257 | scope: *Scope, |
| 2382 | expr: *const clang.Expr, | 2258 | expr: *const clang.Expr, |
| 2383 | used: ResultUsed, | 2259 | used: ResultUsed, |
| 2384 | lrvalue: LRValue, | 2260 | lrvalue: LRValue, |
| 2385 | ) TransError!*ast.Node { | 2261 | ) TransError!Node { |
| 2386 | switch (@ptrCast(*const clang.Stmt, expr).getStmtClass()) { | 2262 | return transStmt(c, scope, @ptrCast(*const clang.Stmt, expr), used, lrvalue); |
| 2387 | .IntegerLiteralClass => { | | |
| 2388 | return transIntegerLiteral(rp, scope, @ptrCast(*const clang.IntegerLiteral, expr), .used, .no_as); | | |
| 2389 | }, | | |
| 2390 | .CharacterLiteralClass => { | | |
| 2391 | return transCharLiteral(rp, scope, @ptrCast(*const clang.CharacterLiteral, expr), .used, .no_as); | | |
| 2392 | }, | | |
| 2393 | .UnaryOperatorClass => { | | |
| 2394 | const un_expr = @ptrCast(*const clang.UnaryOperator, expr); | | |
| 2395 | if (un_expr.getOpcode() == .Extension) { | | |
| 2396 | return transExprCoercing(rp, scope, un_expr.getSubExpr(), used, lrvalue); | | |
| 2397 | } | | |
| 2398 | }, | | |
| 2399 | else => {}, | | |
| 2400 | } | | |
| 2401 | return transExpr(rp, scope, expr, .used, .r_value); | | |
| 2402 | } | 2263 | } |
| 2403 | | 2264 | |
| 2404 | fn transInitListExprRecord( | 2265 | fn transInitListExprRecord( |
| ... | @@ -4150,7 +4011,7 @@ fn qualTypeIsBoolean(qt: clang.QualType) bool { | ... | @@ -4150,7 +4011,7 @@ fn qualTypeIsBoolean(qt: clang.QualType) bool { |
| 4150 | return qualTypeCanon(qt).isBooleanType(); | 4011 | return qualTypeCanon(qt).isBooleanType(); |
| 4151 | } | 4012 | } |
| 4152 | | 4013 | |
| 4153 | fn qualTypeIntBitWidth(rp: RestorePoint, qt: clang.QualType, source_loc: clang.SourceLocation) !u32 { | 4014 | fn qualTypeIntBitWidth(c: *Context, qt: clang.QualType, source_loc: clang.SourceLocation) !u32 { |
| 4154 | const ty = qt.getTypePtr(); | 4015 | const ty = qt.getTypePtr(); |
| 4155 | | 4016 | |
| 4156 | switch (ty.getTypeClass()) { | 4017 | switch (ty.getTypeClass()) { |
| ... | @@ -4174,7 +4035,7 @@ fn qualTypeIntBitWidth(rp: RestorePoint, qt: clang.QualType, source_loc: clang.S | ... | @@ -4174,7 +4035,7 @@ fn qualTypeIntBitWidth(rp: RestorePoint, qt: clang.QualType, source_loc: clang.S |
| 4174 | .Typedef => { | 4035 | .Typedef => { |
| 4175 | const typedef_ty = @ptrCast(*const clang.TypedefType, ty); | 4036 | const typedef_ty = @ptrCast(*const clang.TypedefType, ty); |
| 4176 | const typedef_decl = typedef_ty.getDecl(); | 4037 | const typedef_decl = typedef_ty.getDecl(); |
| 4177 | const type_name = try rp.c.str(@ptrCast(*const clang.NamedDecl, typedef_decl).getName_bytes_begin()); | 4038 | const type_name = try c.str(@ptrCast(*const clang.NamedDecl, typedef_decl).getName_bytes_begin()); |
| 4178 | | 4039 | |
| 4179 | if (mem.eql(u8, type_name, "uint8_t") or mem.eql(u8, type_name, "int8_t")) { | 4040 | if (mem.eql(u8, type_name, "uint8_t") or mem.eql(u8, type_name, "int8_t")) { |
| 4180 | return 8; | 4041 | return 8; |
| ... | @@ -4194,51 +4055,17 @@ fn qualTypeIntBitWidth(rp: RestorePoint, qt: clang.QualType, source_loc: clang.S | ... | @@ -4194,51 +4055,17 @@ fn qualTypeIntBitWidth(rp: RestorePoint, qt: clang.QualType, source_loc: clang.S |
| 4194 | unreachable; | 4055 | unreachable; |
| 4195 | } | 4056 | } |
| 4196 | | 4057 | |
| 4197 | fn qualTypeToLog2IntRef(rp: RestorePoint, qt: clang.QualType, source_loc: clang.SourceLocation) !*ast.Node { | 4058 | fn qualTypeToLog2IntRef(c: *Context, qt: clang.QualType, source_loc: clang.SourceLocation) !Node { |
| 4198 | const int_bit_width = try qualTypeIntBitWidth(rp, qt, source_loc); | 4059 | const int_bit_width = try qualTypeIntBitWidth(c, qt, source_loc); |
| 4199 | | 4060 | |
| 4200 | if (int_bit_width != 0) { | 4061 | if (int_bit_width != 0) { |
| 4201 | // we can perform the log2 now. | 4062 | // we can perform the log2 now. |
| 4202 | const cast_bit_width = math.log2_int(u64, int_bit_width); | 4063 | const cast_bit_width = math.log2_int(u64, int_bit_width); |
| 4203 | const node = try rp.c.arena.create(ast.Node.OneToken); | 4064 | return Node.uint_type.create(c.arena, cast_bit_width); |
| 4204 | node.* = .{ | 4065 | } |
| 4205 | .base = .{ .tag = .IntegerLiteral }, | | |
| 4206 | .token = try appendTokenFmt(rp.c, .Identifier, "u{d}", .{cast_bit_width}), | | |
| 4207 | }; | | |
| 4208 | return &node.base; | | |
| 4209 | } | | |
| 4210 | | | |
| 4211 | const zig_type_node = try transQualType(rp, qt, source_loc); | | |
| 4212 | | | |
| 4213 | // @import("std").math.Log2Int(c_long); | | |
| 4214 | // | | |
| 4215 | // FnCall | | |
| 4216 | // FieldAccess | | |
| 4217 | // FieldAccess | | |
| 4218 | // FnCall (.builtin = true) | | |
| 4219 | // Symbol "import" | | |
| 4220 | // StringLiteral "std" | | |
| 4221 | // Symbol "math" | | |
| 4222 | // Symbol "Log2Int" | | |
| 4223 | // Symbol <zig_type_node> (var from above) | | |
| 4224 | | | |
| 4225 | const import_fn_call = try rp.c.createBuiltinCall("@import", 1); | | |
| 4226 | const std_token = try appendToken(rp.c, .StringLiteral, "\"std\""); | | |
| 4227 | const std_node = try rp.c.arena.create(ast.Node.OneToken); | | |
| 4228 | std_node.* = .{ | | |
| 4229 | .base = .{ .tag = .StringLiteral }, | | |
| 4230 | .token = std_token, | | |
| 4231 | }; | | |
| 4232 | import_fn_call.params()[0] = &std_node.base; | | |
| 4233 | import_fn_call.rparen_token = try appendToken(rp.c, .RParen, ")"); | | |
| 4234 | | | |
| 4235 | const inner_field_access = try transCreateNodeFieldAccess(rp.c, &import_fn_call.base, "math"); | | |
| 4236 | const outer_field_access = try transCreateNodeFieldAccess(rp.c, inner_field_access, "Log2Int"); | | |
| 4237 | const log2int_fn_call = try rp.c.createCall(outer_field_access, 1); | | |
| 4238 | log2int_fn_call.params()[0] = zig_type_node; | | |
| 4239 | log2int_fn_call.rtoken = try appendToken(rp.c, .RParen, ")"); | | |
| 4240 | | 4066 | |
| 4241 | return &log2int_fn_call.base; | 4067 | const zig_type = try transQualType(c, qt, source_loc); |
| | 4068 | return Node.std_math_Log2Int.create(c.arena, zig_type); |
| 4242 | } | 4069 | } |
| 4243 | | 4070 | |
| 4244 | fn qualTypeChildIsFnProto(qt: clang.QualType) bool { | 4071 | fn qualTypeChildIsFnProto(qt: clang.QualType) bool { |
| ... | @@ -4506,67 +4333,6 @@ fn transCreateNodeSimplePrefixOp( | ... | @@ -4506,67 +4333,6 @@ fn transCreateNodeSimplePrefixOp( |
| 4506 | return node; | 4333 | return node; |
| 4507 | } | 4334 | } |
| 4508 | | 4335 | |
| 4509 | fn transCreateNodeInfixOp( | | |
| 4510 | rp: RestorePoint, | | |
| 4511 | scope: *Scope, | | |
| 4512 | lhs_node: *ast.Node, | | |
| 4513 | op: ast.Node.Tag, | | |
| 4514 | op_token: ast.TokenIndex, | | |
| 4515 | rhs_node: *ast.Node, | | |
| 4516 | used: ResultUsed, | | |
| 4517 | grouped: bool, | | |
| 4518 | ) !*ast.Node { | | |
| 4519 | var lparen = if (grouped) | | |
| 4520 | try appendToken(rp.c, .LParen, "(") | | |
| 4521 | else | | |
| 4522 | null; | | |
| 4523 | const node = try rp.c.arena.create(ast.Node.SimpleInfixOp); | | |
| 4524 | node.* = .{ | | |
| 4525 | .base = .{ .tag = op }, | | |
| 4526 | .op_token = op_token, | | |
| 4527 | .lhs = lhs_node, | | |
| 4528 | .rhs = rhs_node, | | |
| 4529 | }; | | |
| 4530 | if (!grouped) return maybeSuppressResult(rp, scope, used, &node.base); | | |
| 4531 | const rparen = try appendToken(rp.c, .RParen, ")"); | | |
| 4532 | const grouped_expr = try rp.c.arena.create(ast.Node.GroupedExpression); | | |
| 4533 | grouped_expr.* = .{ | | |
| 4534 | .lparen = lparen.?, | | |
| 4535 | .expr = &node.base, | | |
| 4536 | .rparen = rparen, | | |
| 4537 | }; | | |
| 4538 | return maybeSuppressResult(rp, scope, used, &grouped_expr.base); | | |
| 4539 | } | | |
| 4540 | | | |
| 4541 | fn transCreateNodeBoolInfixOp( | | |
| 4542 | rp: RestorePoint, | | |
| 4543 | scope: *Scope, | | |
| 4544 | stmt: *const clang.BinaryOperator, | | |
| 4545 | op: ast.Node.Tag, | | |
| 4546 | used: ResultUsed, | | |
| 4547 | grouped: bool, | | |
| 4548 | ) !*ast.Node { | | |
| 4549 | std.debug.assert(op == .BoolAnd or op == .BoolOr); | | |
| 4550 | | | |
| 4551 | const lhs_hode = try transBoolExpr(rp, scope, stmt.getLHS(), .used, .l_value, true); | | |
| 4552 | const op_token = if (op == .BoolAnd) | | |
| 4553 | try appendToken(rp.c, .Keyword_and, "and") | | |
| 4554 | else | | |
| 4555 | try appendToken(rp.c, .Keyword_or, "or"); | | |
| 4556 | const rhs = try transBoolExpr(rp, scope, stmt.getRHS(), .used, .r_value, true); | | |
| 4557 | | | |
| 4558 | return transCreateNodeInfixOp( | | |
| 4559 | rp, | | |
| 4560 | scope, | | |
| 4561 | lhs_hode, | | |
| 4562 | op, | | |
| 4563 | op_token, | | |
| 4564 | rhs, | | |
| 4565 | used, | | |
| 4566 | grouped, | | |
| 4567 | ); | | |
| 4568 | } | | |
| 4569 | | | |
| 4570 | fn transCreateNodePtrType( | 4336 | fn transCreateNodePtrType( |
| 4571 | c: *Context, | 4337 | c: *Context, |
| 4572 | is_const: bool, | 4338 | is_const: bool, |
| ... | @@ -4968,40 +4734,33 @@ fn transCreateNodeSwitchElse(c: *Context) !*ast.Node { | ... | @@ -4968,40 +4734,33 @@ fn transCreateNodeSwitchElse(c: *Context) !*ast.Node { |
| 4968 | } | 4734 | } |
| 4969 | | 4735 | |
| 4970 | fn transCreateNodeShiftOp( | 4736 | fn transCreateNodeShiftOp( |
| 4971 | rp: RestorePoint, | 4737 | c: *Context, |
| 4972 | scope: *Scope, | 4738 | scope: *Scope, |
| 4973 | stmt: *const clang.BinaryOperator, | 4739 | stmt: *const clang.BinaryOperator, |
| 4974 | op: ast.Node.Tag, | 4740 | op: Node.Tag, |
| 4975 | op_tok_id: std.zig.Token.Id, | 4741 | ) !Node { |
| 4976 | bytes: []const u8, | 4742 | std.debug.assert(op == .shl or op == .shr); |
| 4977 | ) !*ast.Node { | | |
| 4978 | std.debug.assert(op == .BitShiftLeft or op == .BitShiftRight); | | |
| 4979 | | 4743 | |
| 4980 | const lhs_expr = stmt.getLHS(); | 4744 | const lhs_expr = stmt.getLHS(); |
| 4981 | const rhs_expr = stmt.getRHS(); | 4745 | const rhs_expr = stmt.getRHS(); |
| 4982 | const rhs_location = rhs_expr.getBeginLoc(); | 4746 | const rhs_location = rhs_expr.getBeginLoc(); |
| 4983 | // lhs >> @as(u5, rh) | 4747 | // lhs >> @as(u5, rh) |
| 4984 | | 4748 | |
| 4985 | const lhs = try transExpr(rp, scope, lhs_expr, .used, .l_value); | 4749 | const lhs = try transExpr(c, scope, lhs_expr, .used, .l_value); |
| 4986 | const op_token = try appendToken(rp.c, op_tok_id, bytes); | | |
| 4987 | | 4750 | |
| 4988 | const cast_node = try rp.c.createBuiltinCall("@intCast", 2); | 4751 | const rhs_type = try qualTypeToLog2IntRef(c, stmt.getType(), rhs_location); |
| 4989 | const rhs_type = try qualTypeToLog2IntRef(rp, stmt.getType(), rhs_location); | 4752 | const rhs = try transExpr(c, scope, rhs_expr, .used, .r_value); |
| 4990 | cast_node.params()[0] = rhs_type; | 4753 | const rhs_casted = try Node.int_cast.create(c.arena, .{ .lhs = rhs_type, .rhs = rhs_type }); |
| 4991 | _ = try appendToken(rp.c, .Comma, ","); | | |
| 4992 | const rhs = try transExprCoercing(rp, scope, rhs_expr, .used, .r_value); | | |
| 4993 | cast_node.params()[1] = rhs; | | |
| 4994 | cast_node.rparen_token = try appendToken(rp.c, .RParen, ")"); | | |
| 4995 | | 4754 | |
| 4996 | const node = try rp.c.arena.create(ast.Node.SimpleInfixOp); | 4755 | const payload = try c.arena.create(ast.Payload.BinOp); |
| 4997 | node.* = .{ | 4756 | payload.* = .{ |
| 4998 | .base = .{ .tag = op }, | 4757 | .base = .{ .tag = op }, |
| 4999 | .op_token = op_token, | 4758 | .data = .{ |
| 5000 | .lhs = lhs, | 4759 | .lhs = lhs, |
| 5001 | .rhs = &cast_node.base, | 4760 | .rhs = rhs_casted, |
| | 4761 | } |
| 5002 | }; | 4762 | }; |
| 5003 | | 4763 | return &payload.base; |
| 5004 | return &node.base; | | |
| 5005 | } | 4764 | } |
| 5006 | | 4765 | |
| 5007 | fn transCreateNodePtrDeref(c: *Context, lhs: *ast.Node) !*ast.Node { | 4766 | fn transCreateNodePtrDeref(c: *Context, lhs: *ast.Node) !*ast.Node { |
| ... | @@ -5025,161 +4784,7 @@ fn transCreateNodeArrayAccess(c: *Context, lhs: *ast.Node) !*ast.Node.ArrayAcces | ... | @@ -5025,161 +4784,7 @@ fn transCreateNodeArrayAccess(c: *Context, lhs: *ast.Node) !*ast.Node.ArrayAcces |
| 5025 | return node; | 4784 | return node; |
| 5026 | } | 4785 | } |
| 5027 | | 4786 | |
| 5028 | const RestorePoint = struct { | 4787 | fn transType(c: *Context, ty: *const clang.Type, source_loc: clang.SourceLocation) TypeError!Type { |
| 5029 | c: *Context, | | |
| 5030 | token_index: ast.TokenIndex, | | |
| 5031 | src_buf_index: usize, | | |
| 5032 | | | |
| 5033 | fn activate(self: RestorePoint) void { | | |
| 5034 | self.c.token_ids.shrinkAndFree(self.c.gpa, self.token_index); | | |
| 5035 | self.c.token_locs.shrinkAndFree(self.c.gpa, self.token_index); | | |
| 5036 | self.c.source_buffer.shrinkAndFree(self.src_buf_index); | | |
| 5037 | } | | |
| 5038 | }; | | |
| 5039 | | | |
| 5040 | fn makeRestorePoint(c: *Context) RestorePoint { | | |
| 5041 | return RestorePoint{ | | |
| 5042 | .c = c, | | |
| 5043 | .token_index = c.token_ids.items.len, | | |
| 5044 | .src_buf_index = c.source_buffer.items.len, | | |
| 5045 | }; | | |
| 5046 | } | | |
| 5047 | | | |
| 5048 | fn transType(rp: RestorePoint, ty: *const clang.Type, source_loc: clang.SourceLocation) TypeError!*ast.Node { | | |
| 5049 | switch (ty.getTypeClass()) { | | |
| 5050 | .Builtin => { | | |
| 5051 | const builtin_ty = @ptrCast(*const clang.BuiltinType, ty); | | |
| 5052 | return transCreateNodeIdentifier(rp.c, switch (builtin_ty.getKind()) { | | |
| 5053 | .Void => "c_void", | | |
| 5054 | .Bool => "bool", | | |
| 5055 | .Char_U, .UChar, .Char_S, .Char8 => "u8", | | |
| 5056 | .SChar => "i8", | | |
| 5057 | .UShort => "c_ushort", | | |
| 5058 | .UInt => "c_uint", | | |
| 5059 | .ULong => "c_ulong", | | |
| 5060 | .ULongLong => "c_ulonglong", | | |
| 5061 | .Short => "c_short", | | |
| 5062 | .Int => "c_int", | | |
| 5063 | .Long => "c_long", | | |
| 5064 | .LongLong => "c_longlong", | | |
| 5065 | .UInt128 => "u128", | | |
| 5066 | .Int128 => "i128", | | |
| 5067 | .Float => "f32", | | |
| 5068 | .Double => "f64", | | |
| 5069 | .Float128 => "f128", | | |
| 5070 | .Float16 => "f16", | | |
| 5071 | .LongDouble => "c_longdouble", | | |
| 5072 | else => return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported builtin type", .{}), | | |
| 5073 | }); | | |
| 5074 | }, | | |
| 5075 | .FunctionProto => { | | |
| 5076 | const fn_proto_ty = @ptrCast(*const clang.FunctionProtoType, ty); | | |
| 5077 | const fn_proto = try transFnProto(rp, null, fn_proto_ty, source_loc, null, false); | | |
| 5078 | return &fn_proto.base; | | |
| 5079 | }, | | |
| 5080 | .FunctionNoProto => { | | |
| 5081 | const fn_no_proto_ty = @ptrCast(*const clang.FunctionType, ty); | | |
| 5082 | const fn_proto = try transFnNoProto(rp, fn_no_proto_ty, source_loc, null, false); | | |
| 5083 | return &fn_proto.base; | | |
| 5084 | }, | | |
| 5085 | .Paren => { | | |
| 5086 | const paren_ty = @ptrCast(*const clang.ParenType, ty); | | |
| 5087 | return transQualType(rp, paren_ty.getInnerType(), source_loc); | | |
| 5088 | }, | | |
| 5089 | .Pointer => { | | |
| 5090 | const child_qt = ty.getPointeeType(); | | |
| 5091 | if (qualTypeChildIsFnProto(child_qt)) { | | |
| 5092 | const optional_node = try transCreateNodeSimplePrefixOp(rp.c, .OptionalType, .QuestionMark, "?"); | | |
| 5093 | optional_node.rhs = try transQualType(rp, child_qt, source_loc); | | |
| 5094 | return &optional_node.base; | | |
| 5095 | } | | |
| 5096 | if (typeIsOpaque(rp.c, child_qt.getTypePtr(), source_loc) or qualTypeWasDemotedToOpaque(rp.c, child_qt)) { | | |
| 5097 | const optional_node = try transCreateNodeSimplePrefixOp(rp.c, .OptionalType, .QuestionMark, "?"); | | |
| 5098 | const pointer_node = try transCreateNodePtrType( | | |
| 5099 | rp.c, | | |
| 5100 | child_qt.isConstQualified(), | | |
| 5101 | child_qt.isVolatileQualified(), | | |
| 5102 | .Asterisk, | | |
| 5103 | ); | | |
| 5104 | optional_node.rhs = &pointer_node.base; | | |
| 5105 | pointer_node.rhs = try transQualType(rp, child_qt, source_loc); | | |
| 5106 | return &optional_node.base; | | |
| 5107 | } | | |
| 5108 | const pointer_node = try transCreateNodePtrType( | | |
| 5109 | rp.c, | | |
| 5110 | child_qt.isConstQualified(), | | |
| 5111 | child_qt.isVolatileQualified(), | | |
| 5112 | .Identifier, | | |
| 5113 | ); | | |
| 5114 | pointer_node.rhs = try transQualType(rp, child_qt, source_loc); | | |
| 5115 | return &pointer_node.base; | | |
| 5116 | }, | | |
| 5117 | .ConstantArray => { | | |
| 5118 | const const_arr_ty = @ptrCast(*const clang.ConstantArrayType, ty); | | |
| 5119 | | | |
| 5120 | const size_ap_int = const_arr_ty.getSize(); | | |
| 5121 | const size = size_ap_int.getLimitedValue(math.maxInt(usize)); | | |
| 5122 | const elem_ty = const_arr_ty.getElementType().getTypePtr(); | | |
| 5123 | return try transCreateNodeArrayType(rp, source_loc, elem_ty, size); | | |
| 5124 | }, | | |
| 5125 | .IncompleteArray => { | | |
| 5126 | const incomplete_array_ty = @ptrCast(*const clang.IncompleteArrayType, ty); | | |
| 5127 | | | |
| 5128 | const child_qt = incomplete_array_ty.getElementType(); | | |
| 5129 | var node = try transCreateNodePtrType( | | |
| 5130 | rp.c, | | |
| 5131 | child_qt.isConstQualified(), | | |
| 5132 | child_qt.isVolatileQualified(), | | |
| 5133 | .Identifier, | | |
| 5134 | ); | | |
| 5135 | node.rhs = try transQualType(rp, child_qt, source_loc); | | |
| 5136 | return &node.base; | | |
| 5137 | }, | | |
| 5138 | .Typedef => { | | |
| 5139 | const typedef_ty = @ptrCast(*const clang.TypedefType, ty); | | |
| 5140 | | | |
| 5141 | const typedef_decl = typedef_ty.getDecl(); | | |
| 5142 | return (try transTypeDef(rp.c, typedef_decl, false)) orelse | | |
| 5143 | revertAndWarn(rp, error.UnsupportedType, source_loc, "unable to translate typedef declaration", .{}); | | |
| 5144 | }, | | |
| 5145 | .Record => { | | |
| 5146 | const record_ty = @ptrCast(*const clang.RecordType, ty); | | |
| 5147 | | | |
| 5148 | const record_decl = record_ty.getDecl(); | | |
| 5149 | return (try transRecordDecl(rp.c, record_decl)) orelse | | |
| 5150 | revertAndWarn(rp, error.UnsupportedType, source_loc, "unable to resolve record declaration", .{}); | | |
| 5151 | }, | | |
| 5152 | .Enum => { | | |
| 5153 | const enum_ty = @ptrCast(*const clang.EnumType, ty); | | |
| 5154 | | | |
| 5155 | const enum_decl = enum_ty.getDecl(); | | |
| 5156 | return (try transEnumDecl(rp.c, enum_decl)) orelse | | |
| 5157 | revertAndWarn(rp, error.UnsupportedType, source_loc, "unable to translate enum declaration", .{}); | | |
| 5158 | }, | | |
| 5159 | .Elaborated => { | | |
| 5160 | const elaborated_ty = @ptrCast(*const clang.ElaboratedType, ty); | | |
| 5161 | return transQualType(rp, elaborated_ty.getNamedType(), source_loc); | | |
| 5162 | }, | | |
| 5163 | .Decayed => { | | |
| 5164 | const decayed_ty = @ptrCast(*const clang.DecayedType, ty); | | |
| 5165 | return transQualType(rp, decayed_ty.getDecayedType(), source_loc); | | |
| 5166 | }, | | |
| 5167 | .Attributed => { | | |
| 5168 | const attributed_ty = @ptrCast(*const clang.AttributedType, ty); | | |
| 5169 | return transQualType(rp, attributed_ty.getEquivalentType(), source_loc); | | |
| 5170 | }, | | |
| 5171 | .MacroQualified => { | | |
| 5172 | const macroqualified_ty = @ptrCast(*const clang.MacroQualifiedType, ty); | | |
| 5173 | return transQualType(rp, macroqualified_ty.getModifiedType(), source_loc); | | |
| 5174 | }, | | |
| 5175 | else => { | | |
| 5176 | const type_name = rp.c.str(ty.getTypeClassName()); | | |
| 5177 | return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported type: '{s}'", .{type_name}); | | |
| 5178 | }, | | |
| 5179 | } | | |
| 5180 | } | | |
| 5181 | | | |
| 5182 | fn transType1(c: *Context, ty: *const clang.Type, source_loc: clang.SourceLocation) TypeError!Type { | | |
| 5183 | switch (ty.getTypeClass()) { | 4788 | switch (ty.getTypeClass()) { |
| 5184 | .Builtin => { | 4789 | .Builtin => { |
| 5185 | const builtin_ty = @ptrCast(*const clang.BuiltinType, ty); | 4790 | const builtin_ty = @ptrCast(*const clang.BuiltinType, ty); |