| ... | ... | @@ -3,14 +3,14 @@ |
| 3 | 3 | |
| 4 | 4 | const std = @import("std"); |
| 5 | 5 | const assert = std.debug.assert; |
| 6 | | const ast = std.zig.ast; |
| 7 | | const Token = std.zig.Token; |
| 8 | 6 | const clang = @import("clang.zig"); |
| 9 | 7 | const ctok = std.c.tokenizer; |
| 10 | 8 | const CToken = std.c.Token; |
| 11 | 9 | const mem = std.mem; |
| 12 | 10 | const math = std.math; |
| 13 | 11 | const Type = @import("type.zig").Type; |
| 12 | const ast = @import("translate_c/ast.zig"); |
| 13 | const Node = ast.Node; |
| 14 | 14 | |
| 15 | 15 | const CallingConvention = std.builtin.CallingConvention; |
| 16 | 16 | |
| ... | ... | @@ -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 | 351 | pub fn translate( |
| 393 | 352 | gpa: *mem.Allocator, |
| 394 | 353 | args_begin: [*]?[*]const u8, |
| ... | ... | @@ -446,7 +405,7 @@ pub fn translate( |
| 446 | 405 | context.opaque_demotes.deinit(gpa); |
| 447 | 406 | } |
| 448 | 407 | |
| 449 | | try addCBuiltinsNamespace(&context); |
| 408 | _ = try Node.usingnamespace_builtins.init(); |
| 450 | 409 | |
| 451 | 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 | 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 | 1280 | const ResultUsed = enum { |
| 1342 | 1281 | used, |
| 1343 | 1282 | unused, |
| ... | ... | @@ -1349,78 +1288,63 @@ const LRValue = enum { |
| 1349 | 1288 | }; |
| 1350 | 1289 | |
| 1351 | 1290 | fn transStmt( |
| 1352 | | rp: RestorePoint, |
| 1291 | c: *Context, |
| 1353 | 1292 | scope: *Scope, |
| 1354 | 1293 | stmt: *const clang.Stmt, |
| 1355 | 1294 | result_used: ResultUsed, |
| 1356 | 1295 | lrvalue: LRValue, |
| 1357 | | ) TransError!*ast.Node { |
| 1296 | ) TransError!Node { |
| 1358 | 1297 | const sc = stmt.getStmtClass(); |
| 1359 | 1298 | switch (sc) { |
| 1360 | | .BinaryOperatorClass => return transBinaryOperator(rp, scope, @ptrCast(*const clang.BinaryOperator, stmt), result_used), |
| 1361 | | .CompoundStmtClass => return transCompoundStmt(rp, scope, @ptrCast(*const clang.CompoundStmt, stmt)), |
| 1362 | | .CStyleCastExprClass => return transCStyleCastExprClass(rp, scope, @ptrCast(*const clang.CStyleCastExpr, stmt), result_used, lrvalue), |
| 1363 | | .DeclStmtClass => return transDeclStmt(rp, scope, @ptrCast(*const clang.DeclStmt, stmt)), |
| 1364 | | .DeclRefExprClass => return transDeclRefExpr(rp, scope, @ptrCast(*const clang.DeclRefExpr, stmt), lrvalue), |
| 1365 | | .ImplicitCastExprClass => return transImplicitCastExpr(rp, scope, @ptrCast(*const clang.ImplicitCastExpr, stmt), result_used), |
| 1366 | | .IntegerLiteralClass => return transIntegerLiteral(rp, scope, @ptrCast(*const clang.IntegerLiteral, stmt), result_used, .with_as), |
| 1367 | | .ReturnStmtClass => return transReturnStmt(rp, scope, @ptrCast(*const clang.ReturnStmt, stmt)), |
| 1368 | | .StringLiteralClass => return transStringLiteral(rp, scope, @ptrCast(*const clang.StringLiteral, stmt), result_used), |
| 1299 | .BinaryOperatorClass => return transBinaryOperator(c, scope, @ptrCast(*const clang.BinaryOperator, stmt), result_used), |
| 1300 | .CompoundStmtClass => return transCompoundStmt(c, scope, @ptrCast(*const clang.CompoundStmt, stmt)), |
| 1301 | .CStyleCastExprClass => return transCStyleCastExprClass(c, scope, @ptrCast(*const clang.CStyleCastExpr, stmt), result_used, lrvalue), |
| 1302 | .DeclStmtClass => return transDeclStmt(c, scope, @ptrCast(*const clang.DeclStmt, stmt)), |
| 1303 | .DeclRefExprClass => return transDeclRefExpr(c, scope, @ptrCast(*const clang.DeclRefExpr, stmt), lrvalue), |
| 1304 | .ImplicitCastExprClass => return transImplicitCastExpr(c, scope, @ptrCast(*const clang.ImplicitCastExpr, stmt), result_used), |
| 1305 | .IntegerLiteralClass => return transIntegerLiteral(c, scope, @ptrCast(*const clang.IntegerLiteral, stmt), result_used, .with_as), |
| 1306 | .ReturnStmtClass => return transReturnStmt(c, scope, @ptrCast(*const clang.ReturnStmt, stmt)), |
| 1307 | .StringLiteralClass => return transStringLiteral(c, scope, @ptrCast(*const clang.StringLiteral, stmt), result_used), |
| 1369 | 1308 | .ParenExprClass => { |
| 1370 | | const expr = try transExpr(rp, scope, @ptrCast(*const clang.ParenExpr, stmt).getSubExpr(), .used, lrvalue); |
| 1371 | | if (expr.tag == .GroupedExpression) return maybeSuppressResult(rp, scope, result_used, expr); |
| 1372 | | const node = try rp.c.arena.create(ast.Node.GroupedExpression); |
| 1373 | | node.* = .{ |
| 1374 | | .lparen = try appendToken(rp.c, .LParen, "("), |
| 1375 | | .expr = expr, |
| 1376 | | .rparen = try appendToken(rp.c, .RParen, ")"), |
| 1377 | | }; |
| 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)), |
| 1309 | const expr = try transExpr(c, scope, @ptrCast(*const clang.ParenExpr, stmt).getSubExpr(), .used, lrvalue); |
| 1310 | return maybeSuppressResult(c, scope, result_used, expr); |
| 1311 | }, |
| 1312 | .InitListExprClass => return transInitListExpr(c, scope, @ptrCast(*const clang.InitListExpr, stmt), result_used), |
| 1313 | .ImplicitValueInitExprClass => return transImplicitValueInitExpr(c, scope, @ptrCast(*const clang.Expr, stmt), result_used), |
| 1314 | .IfStmtClass => return transIfStmt(c, scope, @ptrCast(*const clang.IfStmt, stmt)), |
| 1315 | .WhileStmtClass => return transWhileLoop(c, scope, @ptrCast(*const clang.WhileStmt, stmt)), |
| 1316 | .DoStmtClass => return transDoWhileLoop(c, scope, @ptrCast(*const clang.DoStmt, stmt)), |
| 1385 | 1317 | .NullStmtClass => { |
| 1386 | | const block = try rp.c.createBlock(0); |
| 1387 | | block.rbrace = try appendToken(rp.c, .RBrace, "}"); |
| 1388 | | return &block.base; |
| 1389 | | }, |
| 1390 | | .ContinueStmtClass => return try transCreateNodeContinue(rp.c), |
| 1391 | | .BreakStmtClass => return transBreak(rp, scope), |
| 1392 | | .ForStmtClass => return transForLoop(rp, scope, @ptrCast(*const clang.ForStmt, stmt)), |
| 1393 | | .FloatingLiteralClass => return transFloatingLiteral(rp, scope, @ptrCast(*const clang.FloatingLiteral, stmt), result_used), |
| 1318 | return Node.empty_block.init(); |
| 1319 | }, |
| 1320 | .ContinueStmtClass => return try transCreateNodeContinue(c), |
| 1321 | .BreakStmtClass => return transBreak(c, scope), |
| 1322 | .ForStmtClass => return transForLoop(c, scope, @ptrCast(*const clang.ForStmt, stmt)), |
| 1323 | .FloatingLiteralClass => return transFloatingLiteral(c, scope, @ptrCast(*const clang.FloatingLiteral, stmt), result_used), |
| 1394 | 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 | 1327 | .BinaryConditionalOperatorClass => { |
| 1398 | | return transBinaryConditionalOperator(rp, scope, @ptrCast(*const clang.BinaryConditionalOperator, stmt), result_used); |
| 1399 | | }, |
| 1400 | | .SwitchStmtClass => return transSwitch(rp, scope, @ptrCast(*const clang.SwitchStmt, stmt)), |
| 1401 | | .CaseStmtClass => return transCase(rp, scope, @ptrCast(*const clang.CaseStmt, stmt)), |
| 1402 | | .DefaultStmtClass => return transDefault(rp, scope, @ptrCast(*const clang.DefaultStmt, stmt)), |
| 1403 | | .ConstantExprClass => return transConstantExpr(rp, scope, @ptrCast(*const clang.Expr, stmt), result_used), |
| 1404 | | .PredefinedExprClass => return transPredefinedExpr(rp, scope, @ptrCast(*const clang.PredefinedExpr, stmt), result_used), |
| 1405 | | .CharacterLiteralClass => return transCharLiteral(rp, scope, @ptrCast(*const clang.CharacterLiteral, stmt), result_used, .with_as), |
| 1406 | | .StmtExprClass => return transStmtExpr(rp, scope, @ptrCast(*const clang.StmtExpr, stmt), result_used), |
| 1407 | | .MemberExprClass => return transMemberExpr(rp, scope, @ptrCast(*const clang.MemberExpr, stmt), result_used), |
| 1408 | | .ArraySubscriptExprClass => return transArrayAccess(rp, scope, @ptrCast(*const clang.ArraySubscriptExpr, stmt), result_used), |
| 1409 | | .CallExprClass => return transCallExpr(rp, scope, @ptrCast(*const clang.CallExpr, stmt), result_used), |
| 1410 | | .UnaryExprOrTypeTraitExprClass => return transUnaryExprOrTypeTraitExpr(rp, scope, @ptrCast(*const clang.UnaryExprOrTypeTraitExpr, stmt), result_used), |
| 1411 | | .UnaryOperatorClass => return transUnaryOperator(rp, scope, @ptrCast(*const clang.UnaryOperator, stmt), result_used), |
| 1412 | | .CompoundAssignOperatorClass => return transCompoundAssignOperator(rp, scope, @ptrCast(*const clang.CompoundAssignOperator, stmt), result_used), |
| 1328 | return transBinaryConditionalOperator(c, scope, @ptrCast(*const clang.BinaryConditionalOperator, stmt), result_used); |
| 1329 | }, |
| 1330 | .SwitchStmtClass => return transSwitch(c, scope, @ptrCast(*const clang.SwitchStmt, stmt)), |
| 1331 | .CaseStmtClass => return transCase(c, scope, @ptrCast(*const clang.CaseStmt, stmt)), |
| 1332 | .DefaultStmtClass => return transDefault(c, scope, @ptrCast(*const clang.DefaultStmt, stmt)), |
| 1333 | .ConstantExprClass => return transConstantExpr(c, scope, @ptrCast(*const clang.Expr, stmt), result_used), |
| 1334 | .PredefinedExprClass => return transPredefinedExpr(c, scope, @ptrCast(*const clang.PredefinedExpr, stmt), result_used), |
| 1335 | .CharacterLiteralClass => return transCharLiteral(c, scope, @ptrCast(*const clang.CharacterLiteral, stmt), result_used, .with_as), |
| 1336 | .StmtExprClass => return transStmtExpr(c, scope, @ptrCast(*const clang.StmtExpr, stmt), result_used), |
| 1337 | .MemberExprClass => return transMemberExpr(c, scope, @ptrCast(*const clang.MemberExpr, stmt), result_used), |
| 1338 | .ArraySubscriptExprClass => return transArrayAccess(c, scope, @ptrCast(*const clang.ArraySubscriptExpr, stmt), result_used), |
| 1339 | .CallExprClass => return transCallExpr(c, scope, @ptrCast(*const clang.CallExpr, stmt), result_used), |
| 1340 | .UnaryExprOrTypeTraitExprClass => return transUnaryExprOrTypeTraitExpr(c, scope, @ptrCast(*const clang.UnaryExprOrTypeTraitExpr, stmt), result_used), |
| 1341 | .UnaryOperatorClass => return transUnaryOperator(c, scope, @ptrCast(*const clang.UnaryOperator, stmt), result_used), |
| 1342 | .CompoundAssignOperatorClass => return transCompoundAssignOperator(c, scope, @ptrCast(*const clang.CompoundAssignOperator, stmt), result_used), |
| 1413 | 1343 | .OpaqueValueExprClass => { |
| 1414 | 1344 | const source_expr = @ptrCast(*const clang.OpaqueValueExpr, stmt).getSourceExpr().?; |
| 1415 | | const expr = try transExpr(rp, scope, source_expr, .used, lrvalue); |
| 1416 | | if (expr.tag == .GroupedExpression) return maybeSuppressResult(rp, scope, result_used, expr); |
| 1417 | | const node = try rp.c.arena.create(ast.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); |
| 1345 | const expr = try transExpr(c, scope, source_expr, .used, lrvalue); |
| 1346 | return maybeSuppressResult(c, scope, result_used, expr); |
| 1347 | const node = try c.arena.create(Node.GroupedExpression); |
| 1424 | 1348 | }, |
| 1425 | 1349 | else => { |
| 1426 | 1350 | return revertAndWarn( |
| ... | ... | @@ -1435,175 +1359,139 @@ fn transStmt( |
| 1435 | 1359 | } |
| 1436 | 1360 | |
| 1437 | 1361 | fn transBinaryOperator( |
| 1438 | | rp: RestorePoint, |
| 1362 | c: *Context, |
| 1439 | 1363 | scope: *Scope, |
| 1440 | 1364 | stmt: *const clang.BinaryOperator, |
| 1441 | 1365 | result_used: ResultUsed, |
| 1442 | | ) TransError!*ast.Node { |
| 1366 | ) TransError!Node { |
| 1443 | 1367 | const op = stmt.getOpcode(); |
| 1444 | 1368 | const qt = stmt.getType(); |
| 1445 | | var op_token: ast.TokenIndex = undefined; |
| 1446 | | var op_id: ast.Node.Tag = undefined; |
| 1447 | 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 | 1371 | .Comma => { |
| 1450 | 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 | 1377 | try block_scope.statements.append(lhs); |
| 1455 | 1378 | |
| 1456 | 1379 | const rhs = try transExpr(rp, &block_scope.base, stmt.getRHS(), .used, .r_value); |
| 1457 | | _ = try appendToken(rp.c, .Semicolon, ";"); |
| 1458 | | const break_node = try transCreateNodeBreak(rp.c, block_scope.label, rhs); |
| 1459 | | try block_scope.statements.append(&break_node.base); |
| 1380 | const break_node = try Node.break_val.create(c.arena, .{ |
| 1381 | .label = block_scope.label, |
| 1382 | .val = rhs, |
| 1383 | }); |
| 1384 | try block_scope.statements.append(break_node); |
| 1460 | 1385 | const block_node = try block_scope.complete(rp.c); |
| 1461 | | const rparen = try appendToken(rp.c, .RParen, ")"); |
| 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); |
| 1386 | return maybeSuppressResult(rp, scope, result_used, block_node); |
| 1469 | 1387 | }, |
| 1470 | 1388 | .Div => { |
| 1471 | 1389 | if (cIsSignedInteger(qt)) { |
| 1472 | 1390 | // signed integer division uses @divTrunc |
| 1473 | | const div_trunc_node = try rp.c.createBuiltinCall("@divTrunc", 2); |
| 1474 | | div_trunc_node.params()[0] = try transExpr(rp, scope, stmt.getLHS(), .used, .l_value); |
| 1475 | | _ = try appendToken(rp.c, .Comma, ","); |
| 1476 | | const rhs = try transExpr(rp, scope, stmt.getRHS(), .used, .r_value); |
| 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); |
| 1391 | const lhs = try transExpr(c, scope, stmt.getLHS(), .used, .l_value); |
| 1392 | const rhs = try transExpr(c, scope, stmt.getRHS(), .used, .r_value); |
| 1393 | const div_trunc = try Node.div_trunc.create(c.arena, .{ .lhs = lhs, .rhs = rhs}); |
| 1394 | return maybeSuppressResult(c, scope, result_used, div_trunc); |
| 1480 | 1395 | } |
| 1481 | 1396 | }, |
| 1482 | 1397 | .Rem => { |
| 1483 | 1398 | if (cIsSignedInteger(qt)) { |
| 1484 | 1399 | // signed integer division uses @rem |
| 1485 | | const rem_node = try rp.c.createBuiltinCall("@rem", 2); |
| 1486 | | rem_node.params()[0] = try transExpr(rp, scope, stmt.getLHS(), .used, .l_value); |
| 1487 | | _ = try appendToken(rp.c, .Comma, ","); |
| 1488 | | const rhs = try transExpr(rp, scope, stmt.getRHS(), .used, .r_value); |
| 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); |
| 1400 | const lhs = try transExpr(c, scope, stmt.getLHS(), .used, .l_value); |
| 1401 | const rhs = try transExpr(c, scope, stmt.getRHS(), .used, .r_value); |
| 1402 | const rem = try Node.rem.create(c.arena, .{ .lhs = lhs, .rhs = rhs}); |
| 1403 | return maybeSuppressResult(c, scope, result_used, rem); |
| 1492 | 1404 | } |
| 1493 | 1405 | }, |
| 1494 | 1406 | .Shl => { |
| 1495 | | const node = try transCreateNodeShiftOp(rp, scope, stmt, .BitShiftLeft, .AngleBracketAngleBracketLeft, "<<"); |
| 1496 | | return maybeSuppressResult(rp, scope, result_used, node); |
| 1407 | const node = try transCreateNodeShiftOp(c, scope, stmt, .shl); |
| 1408 | return maybeSuppressResult(c, scope, result_used, node); |
| 1497 | 1409 | }, |
| 1498 | 1410 | .Shr => { |
| 1499 | | const node = try transCreateNodeShiftOp(rp, scope, stmt, .BitShiftRight, .AngleBracketAngleBracketRight, ">>"); |
| 1500 | | return maybeSuppressResult(rp, 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); |
| 1411 | const node = try transCreateNodeShiftOp(c, scope, stmt, .shr); |
| 1412 | return maybeSuppressResult(c, scope, result_used, node); |
| 1509 | 1413 | }, |
| 1510 | 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 | 1417 | switch (op) { |
| 1514 | 1418 | .Add => { |
| 1515 | 1419 | if (cIsUnsignedInteger(qt)) { |
| 1516 | | op_token = try appendToken(rp.c, .PlusPercent, "+%"); |
| 1517 | | op_id = .AddWrap; |
| 1420 | op_id = .add_wrap; |
| 1518 | 1421 | } else { |
| 1519 | | op_token = try appendToken(rp.c, .Plus, "+"); |
| 1520 | | op_id = .Add; |
| 1422 | op_id = .add; |
| 1521 | 1423 | } |
| 1522 | 1424 | }, |
| 1523 | 1425 | .Sub => { |
| 1524 | 1426 | if (cIsUnsignedInteger(qt)) { |
| 1525 | | op_token = try appendToken(rp.c, .MinusPercent, "-%"); |
| 1526 | | op_id = .SubWrap; |
| 1427 | op_id = .sub_wrap; |
| 1527 | 1428 | } else { |
| 1528 | | op_token = try appendToken(rp.c, .Minus, "-"); |
| 1529 | | op_id = .Sub; |
| 1429 | op_id = .sub; |
| 1530 | 1430 | } |
| 1531 | 1431 | }, |
| 1532 | 1432 | .Mul => { |
| 1533 | 1433 | if (cIsUnsignedInteger(qt)) { |
| 1534 | | op_token = try appendToken(rp.c, .AsteriskPercent, "*%"); |
| 1535 | | op_id = .MulWrap; |
| 1434 | op_id = .mul_wrap; |
| 1536 | 1435 | } else { |
| 1537 | | op_token = try appendToken(rp.c, .Asterisk, "*"); |
| 1538 | | op_id = .Mul; |
| 1436 | op_id = .mul; |
| 1539 | 1437 | } |
| 1540 | 1438 | }, |
| 1541 | 1439 | .Div => { |
| 1542 | 1440 | // unsigned/float division uses the operator |
| 1543 | | op_id = .Div; |
| 1544 | | op_token = try appendToken(rp.c, .Slash, "/"); |
| 1441 | op_id = .div; |
| 1545 | 1442 | }, |
| 1546 | 1443 | .Rem => { |
| 1547 | 1444 | // unsigned/float division uses the operator |
| 1548 | | op_id = .Mod; |
| 1549 | | op_token = try appendToken(rp.c, .Percent, "%"); |
| 1445 | op_id = .mod; |
| 1550 | 1446 | }, |
| 1551 | 1447 | .LT => { |
| 1552 | | op_id = .LessThan; |
| 1553 | | op_token = try appendToken(rp.c, .AngleBracketLeft, "<"); |
| 1448 | op_id = .less_than; |
| 1554 | 1449 | }, |
| 1555 | 1450 | .GT => { |
| 1556 | | op_id = .GreaterThan; |
| 1557 | | op_token = try appendToken(rp.c, .AngleBracketRight, ">"); |
| 1451 | op_id = .greater_than; |
| 1558 | 1452 | }, |
| 1559 | 1453 | .LE => { |
| 1560 | | op_id = .LessOrEqual; |
| 1561 | | op_token = try appendToken(rp.c, .AngleBracketLeftEqual, "<="); |
| 1454 | op_id = .less_than_equal; |
| 1562 | 1455 | }, |
| 1563 | 1456 | .GE => { |
| 1564 | | op_id = .GreaterOrEqual; |
| 1565 | | op_token = try appendToken(rp.c, .AngleBracketRightEqual, ">="); |
| 1457 | op_id = .greater_than_equal; |
| 1566 | 1458 | }, |
| 1567 | 1459 | .EQ => { |
| 1568 | | op_id = .EqualEqual; |
| 1569 | | op_token = try appendToken(rp.c, .EqualEqual, "=="); |
| 1460 | op_id = .equal; |
| 1570 | 1461 | }, |
| 1571 | 1462 | .NE => { |
| 1572 | | op_id = .BangEqual; |
| 1573 | | op_token = try appendToken(rp.c, .BangEqual, "!="); |
| 1463 | op_id = .not_equal; |
| 1574 | 1464 | }, |
| 1575 | 1465 | .And => { |
| 1576 | | op_id = .BitAnd; |
| 1577 | | op_token = try appendToken(rp.c, .Ampersand, "&"); |
| 1466 | op_id = .bit_and; |
| 1578 | 1467 | }, |
| 1579 | 1468 | .Xor => { |
| 1580 | | op_id = .BitXor; |
| 1581 | | op_token = try appendToken(rp.c, .Caret, "^"); |
| 1469 | op_id = .bit_xor; |
| 1582 | 1470 | }, |
| 1583 | 1471 | .Or => { |
| 1584 | | op_id = .BitOr; |
| 1585 | | op_token = try appendToken(rp.c, .Pipe, "|"); |
| 1472 | op_id = .bit_or; |
| 1473 | }, |
| 1474 | .LAnd => { |
| 1475 | op_id = .@"and"; |
| 1476 | }, |
| 1477 | .LOr => { |
| 1478 | op_id = .@"or"; |
| 1586 | 1479 | }, |
| 1587 | 1480 | else => unreachable, |
| 1588 | 1481 | } |
| 1589 | 1482 | |
| 1590 | | const rhs_node = try transExpr(rp, scope, stmt.getRHS(), .used, .r_value); |
| 1591 | | |
| 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; |
| 1483 | const lhs = try transExpr(c, scope, stmt.getLHS(), .used, .l_value); |
| 1484 | const rhs = try transExpr(c, scope, stmt.getRHS(), .used, .r_value); |
| 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 | 1497 | fn transCompoundStmtInline( |
| ... | ... | @@ -2365,40 +2253,13 @@ fn transEnumToInt(c: *Context, enum_expr: *ast.Node) TypeError!*ast.Node { |
| 2365 | 2253 | } |
| 2366 | 2254 | |
| 2367 | 2255 | fn transExpr( |
| 2368 | | rp: RestorePoint, |
| 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, |
| 2256 | c: *Context, |
| 2381 | 2257 | scope: *Scope, |
| 2382 | 2258 | expr: *const clang.Expr, |
| 2383 | 2259 | used: ResultUsed, |
| 2384 | 2260 | lrvalue: LRValue, |
| 2385 | | ) TransError!*ast.Node { |
| 2386 | | switch (@ptrCast(*const clang.Stmt, expr).getStmtClass()) { |
| 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); |
| 2261 | ) TransError!Node { |
| 2262 | return transStmt(c, scope, @ptrCast(*const clang.Stmt, expr), used, lrvalue); |
| 2402 | 2263 | } |
| 2403 | 2264 | |
| 2404 | 2265 | fn transInitListExprRecord( |
| ... | ... | @@ -4150,7 +4011,7 @@ fn qualTypeIsBoolean(qt: clang.QualType) bool { |
| 4150 | 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 | 4015 | const ty = qt.getTypePtr(); |
| 4155 | 4016 | |
| 4156 | 4017 | switch (ty.getTypeClass()) { |
| ... | ... | @@ -4174,7 +4035,7 @@ fn qualTypeIntBitWidth(rp: RestorePoint, qt: clang.QualType, source_loc: clang.S |
| 4174 | 4035 | .Typedef => { |
| 4175 | 4036 | const typedef_ty = @ptrCast(*const clang.TypedefType, ty); |
| 4176 | 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 | 4040 | if (mem.eql(u8, type_name, "uint8_t") or mem.eql(u8, type_name, "int8_t")) { |
| 4180 | 4041 | return 8; |
| ... | ... | @@ -4194,51 +4055,17 @@ fn qualTypeIntBitWidth(rp: RestorePoint, qt: clang.QualType, source_loc: clang.S |
| 4194 | 4055 | unreachable; |
| 4195 | 4056 | } |
| 4196 | 4057 | |
| 4197 | | fn qualTypeToLog2IntRef(rp: RestorePoint, qt: clang.QualType, source_loc: clang.SourceLocation) !*ast.Node { |
| 4198 | | const int_bit_width = try qualTypeIntBitWidth(rp, qt, source_loc); |
| 4058 | fn qualTypeToLog2IntRef(c: *Context, qt: clang.QualType, source_loc: clang.SourceLocation) !Node { |
| 4059 | const int_bit_width = try qualTypeIntBitWidth(c, qt, source_loc); |
| 4199 | 4060 | |
| 4200 | 4061 | if (int_bit_width != 0) { |
| 4201 | 4062 | // we can perform the log2 now. |
| 4202 | 4063 | const cast_bit_width = math.log2_int(u64, int_bit_width); |
| 4203 | | const node = try rp.c.arena.create(ast.Node.OneToken); |
| 4204 | | node.* = .{ |
| 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, ")"); |
| 4064 | return Node.uint_type.create(c.arena, cast_bit_width); |
| 4065 | } |
| 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 | 4071 | fn qualTypeChildIsFnProto(qt: clang.QualType) bool { |
| ... | ... | @@ -4506,67 +4333,6 @@ fn transCreateNodeSimplePrefixOp( |
| 4506 | 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 | 4336 | fn transCreateNodePtrType( |
| 4571 | 4337 | c: *Context, |
| 4572 | 4338 | is_const: bool, |
| ... | ... | @@ -4968,40 +4734,33 @@ fn transCreateNodeSwitchElse(c: *Context) !*ast.Node { |
| 4968 | 4734 | } |
| 4969 | 4735 | |
| 4970 | 4736 | fn transCreateNodeShiftOp( |
| 4971 | | rp: RestorePoint, |
| 4737 | c: *Context, |
| 4972 | 4738 | scope: *Scope, |
| 4973 | 4739 | stmt: *const clang.BinaryOperator, |
| 4974 | | op: ast.Node.Tag, |
| 4975 | | op_tok_id: std.zig.Token.Id, |
| 4976 | | bytes: []const u8, |
| 4977 | | ) !*ast.Node { |
| 4978 | | std.debug.assert(op == .BitShiftLeft or op == .BitShiftRight); |
| 4740 | op: Node.Tag, |
| 4741 | ) !Node { |
| 4742 | std.debug.assert(op == .shl or op == .shr); |
| 4979 | 4743 | |
| 4980 | 4744 | const lhs_expr = stmt.getLHS(); |
| 4981 | 4745 | const rhs_expr = stmt.getRHS(); |
| 4982 | 4746 | const rhs_location = rhs_expr.getBeginLoc(); |
| 4983 | 4747 | // lhs >> @as(u5, rh) |
| 4984 | 4748 | |
| 4985 | | const lhs = try transExpr(rp, scope, lhs_expr, .used, .l_value); |
| 4986 | | const op_token = try appendToken(rp.c, op_tok_id, bytes); |
| 4749 | const lhs = try transExpr(c, scope, lhs_expr, .used, .l_value); |
| 4987 | 4750 | |
| 4988 | | const cast_node = try rp.c.createBuiltinCall("@intCast", 2); |
| 4989 | | const rhs_type = try qualTypeToLog2IntRef(rp, stmt.getType(), rhs_location); |
| 4990 | | cast_node.params()[0] = 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, ")"); |
| 4751 | const rhs_type = try qualTypeToLog2IntRef(c, stmt.getType(), rhs_location); |
| 4752 | const rhs = try transExpr(c, scope, rhs_expr, .used, .r_value); |
| 4753 | const rhs_casted = try Node.int_cast.create(c.arena, .{ .lhs = rhs_type, .rhs = rhs_type }); |
| 4995 | 4754 | |
| 4996 | | const node = try rp.c.arena.create(ast.Node.SimpleInfixOp); |
| 4997 | | node.* = .{ |
| 4755 | const payload = try c.arena.create(ast.Payload.BinOp); |
| 4756 | payload.* = .{ |
| 4998 | 4757 | .base = .{ .tag = op }, |
| 4999 | | .op_token = op_token, |
| 5000 | | .lhs = lhs, |
| 5001 | | .rhs = &cast_node.base, |
| 4758 | .data = .{ |
| 4759 | .lhs = lhs, |
| 4760 | .rhs = rhs_casted, |
| 4761 | } |
| 5002 | 4762 | }; |
| 5003 | | |
| 5004 | | return &node.base; |
| 4763 | return &payload.base; |
| 5005 | 4764 | } |
| 5006 | 4765 | |
| 5007 | 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 | 4784 | return node; |
| 5026 | 4785 | } |
| 5027 | 4786 | |
| 5028 | | const RestorePoint = struct { |
| 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 { |
| 4787 | fn transType(c: *Context, ty: *const clang.Type, source_loc: clang.SourceLocation) TypeError!Type { |
| 5183 | 4788 | switch (ty.getTypeClass()) { |
| 5184 | 4789 | .Builtin => { |
| 5185 | 4790 | const builtin_ty = @ptrCast(*const clang.BuiltinType, ty); |