| ... | ... | @@ -943,26 +943,110 @@ fn transBinaryOperator( |
| 943 | 943 | return maybeSuppressResult(rp, scope, result_used, node); |
| 944 | 944 | } |
| 945 | 945 | }, |
| 946 | | .Shl, |
| 947 | | .Shr, |
| 948 | | .LT, |
| 949 | | .GT, |
| 950 | | .LE, |
| 951 | | .GE, |
| 952 | | .EQ, |
| 953 | | .NE, |
| 954 | | .And, |
| 955 | | .Xor, |
| 956 | | .Or, |
| 957 | | .LAnd, |
| 958 | | .LOr, |
| 959 | | => return revertAndWarn( |
| 960 | | rp, |
| 961 | | error.UnsupportedTranslation, |
| 962 | | ZigClangBinaryOperator_getBeginLoc(stmt), |
| 963 | | "TODO: handle more C binary operators: {}", |
| 964 | | .{op}, |
| 965 | | ), |
| 946 | .Shl => { |
| 947 | const node = try transCreateNodeShiftOp(rp, scope, stmt, .BitShiftLeft, .AngleBracketAngleBracketLeft, "<<"); |
| 948 | return maybeSuppressResult(rp, scope, result_used, TransResult{ |
| 949 | .node = node, |
| 950 | .child_scope = scope, |
| 951 | .node_scope = scope, |
| 952 | }); |
| 953 | }, |
| 954 | .Shr => { |
| 955 | const node = try transCreateNodeShiftOp(rp, scope, stmt, .BitShiftRight, .AngleBracketAngleBracketRight, ">>"); |
| 956 | return maybeSuppressResult(rp, scope, result_used, TransResult{ |
| 957 | .node = node, |
| 958 | .child_scope = scope, |
| 959 | .node_scope = scope, |
| 960 | }); |
| 961 | }, |
| 962 | .LT => { |
| 963 | const node = try transCreateNodeInfixOp(rp, scope, stmt, .LessThan, .AngleBracketLeft, "<", true); |
| 964 | return maybeSuppressResult(rp, scope, result_used, TransResult{ |
| 965 | .node = node, |
| 966 | .child_scope = scope, |
| 967 | .node_scope = scope, |
| 968 | }); |
| 969 | }, |
| 970 | .GT => { |
| 971 | const node = try transCreateNodeInfixOp(rp, scope, stmt, .GreaterThan, .AngleBracketRight, ">", true); |
| 972 | return maybeSuppressResult(rp, scope, result_used, TransResult{ |
| 973 | .node = node, |
| 974 | .child_scope = scope, |
| 975 | .node_scope = scope, |
| 976 | }); |
| 977 | }, |
| 978 | .LE => { |
| 979 | const node = try transCreateNodeInfixOp(rp, scope, stmt, .LessOrEqual, .AngleBracketLeftEqual, "<=", true); |
| 980 | return maybeSuppressResult(rp, scope, result_used, TransResult{ |
| 981 | .node = node, |
| 982 | .child_scope = scope, |
| 983 | .node_scope = scope, |
| 984 | }); |
| 985 | }, |
| 986 | .GE => { |
| 987 | const node = try transCreateNodeInfixOp(rp, scope, stmt, .GreaterOrEqual, .AngleBracketRightEqual, ">=", true); |
| 988 | return maybeSuppressResult(rp, scope, result_used, TransResult{ |
| 989 | .node = node, |
| 990 | .child_scope = scope, |
| 991 | .node_scope = scope, |
| 992 | }); |
| 993 | }, |
| 994 | .EQ => { |
| 995 | const node = try transCreateNodeInfixOp(rp, scope, stmt, .EqualEqual, .EqualEqual, "==", true); |
| 996 | return maybeSuppressResult(rp, scope, result_used, TransResult{ |
| 997 | .node = node, |
| 998 | .child_scope = scope, |
| 999 | .node_scope = scope, |
| 1000 | }); |
| 1001 | }, |
| 1002 | .NE => { |
| 1003 | const node = try transCreateNodeInfixOp(rp, scope, stmt, .BangEqual, .BangEqual, "!=", true); |
| 1004 | return maybeSuppressResult(rp, scope, result_used, TransResult{ |
| 1005 | .node = node, |
| 1006 | .child_scope = scope, |
| 1007 | .node_scope = scope, |
| 1008 | }); |
| 1009 | }, |
| 1010 | .And => { |
| 1011 | const node = try transCreateNodeInfixOp(rp, scope, stmt, .BitAnd, .Ampersand, "&", true); |
| 1012 | return maybeSuppressResult(rp, scope, result_used, TransResult{ |
| 1013 | .node = node, |
| 1014 | .child_scope = scope, |
| 1015 | .node_scope = scope, |
| 1016 | }); |
| 1017 | }, |
| 1018 | .Xor => { |
| 1019 | const node = try transCreateNodeInfixOp(rp, scope, stmt, .BitXor, .Caret, "^", true); |
| 1020 | return maybeSuppressResult(rp, scope, result_used, TransResult{ |
| 1021 | .node = node, |
| 1022 | .child_scope = scope, |
| 1023 | .node_scope = scope, |
| 1024 | }); |
| 1025 | }, |
| 1026 | .Or => { |
| 1027 | const node = try transCreateNodeInfixOp(rp, scope, stmt, .BitOr, .Pipe, "|", true); |
| 1028 | return maybeSuppressResult(rp, scope, result_used, TransResult{ |
| 1029 | .node = node, |
| 1030 | .child_scope = scope, |
| 1031 | .node_scope = scope, |
| 1032 | }); |
| 1033 | }, |
| 1034 | .LAnd => { |
| 1035 | const node = try transCreateNodeBoolInfixOp(rp, scope, stmt, .BoolAnd, .Keyword_and, "and"); |
| 1036 | return maybeSuppressResult(rp, scope, result_used, TransResult{ |
| 1037 | .node = node, |
| 1038 | .child_scope = scope, |
| 1039 | .node_scope = scope, |
| 1040 | }); |
| 1041 | }, |
| 1042 | .LOr => { |
| 1043 | const node = try transCreateNodeBoolInfixOp(rp, scope, stmt, .BoolOr, .Keyword_or, "or"); |
| 1044 | return maybeSuppressResult(rp, scope, result_used, TransResult{ |
| 1045 | .node = node, |
| 1046 | .child_scope = scope, |
| 1047 | .node_scope = scope, |
| 1048 | }); |
| 1049 | }, |
| 966 | 1050 | .Comma => { |
| 967 | 1051 | const block_scope = try scope.findBlockScope(rp.c); |
| 968 | 1052 | const expr = block_scope.base.parent == scope; |
| ... | ... | @@ -1147,6 +1231,327 @@ fn transImplicitCastExpr( |
| 1147 | 1231 | } |
| 1148 | 1232 | } |
| 1149 | 1233 | |
| 1234 | fn toEnumZeroCmp( |
| 1235 | rp: RestorePoint, |
| 1236 | scope: *Scope, |
| 1237 | expr: *ast.Node, |
| 1238 | generate_enum_node: fn (RestorePoint, *const struct_ZigClangType, source_loc: ZigClangSourceLocation) TransError!*ast.Node, |
| 1239 | enum_ty: *const struct_ZigClangType, |
| 1240 | enum_source_loc: ZigClangSourceLocation, |
| 1241 | ) !*ast.Node { |
| 1242 | // expr != @bitCast(EnumType, @as(@TagType(EnumType), 0)) |
| 1243 | |
| 1244 | // @bitCast(Enum, |
| 1245 | const bitcast = try transCreateNodeBuiltinFnCall(rp.c, "@bitCast"); |
| 1246 | const bitcast_enum_identifier = try generate_enum_node(rp, enum_ty, enum_source_loc); |
| 1247 | try bitcast.params.push(bitcast_enum_identifier); |
| 1248 | _ = try appendToken(rp.c, .Comma, ","); |
| 1249 | |
| 1250 | // @as( |
| 1251 | const cast_node = try transCreateNodeBuiltinFnCall(rp.c, "@as"); |
| 1252 | |
| 1253 | // @TagType(Enum), |
| 1254 | const tag_type = try transCreateNodeBuiltinFnCall(rp.c, "@TagType"); |
| 1255 | const tag_type_enum_identifier = try generate_enum_node(rp, enum_ty, enum_source_loc); |
| 1256 | try tag_type.params.push(tag_type_enum_identifier); |
| 1257 | tag_type.rparen_token = try appendToken(rp.c, .RParen, ")"); |
| 1258 | try cast_node.params.push(&tag_type.base); |
| 1259 | _ = try appendToken(rp.c, .Comma, ","); |
| 1260 | |
| 1261 | // 0) |
| 1262 | const zero = try transCreateNodeInt(rp.c, 0); |
| 1263 | try cast_node.params.push(zero); |
| 1264 | cast_node.rparen_token = try appendToken(rp.c, .RParen, ")"); |
| 1265 | |
| 1266 | try bitcast.params.push(&cast_node.base); |
| 1267 | bitcast.rparen_token = try appendToken(rp.c, .RParen, ")"); |
| 1268 | |
| 1269 | // expr != @bitCast(EnumType, @as(@TagType(EnumType), 0)) |
| 1270 | return transCreateNodeNotEqual(rp, scope, expr, &bitcast.base); |
| 1271 | } |
| 1272 | |
| 1273 | fn transBoolExpr( |
| 1274 | rp: RestorePoint, |
| 1275 | scope: *Scope, |
| 1276 | expr: *const ZigClangExpr, |
| 1277 | used: ResultUsed, |
| 1278 | lrvalue: LRValue, |
| 1279 | ) !*ast.Node { |
| 1280 | var res = try transExpr(rp, scope, expr, used, lrvalue); |
| 1281 | |
| 1282 | switch (res.node.id) { |
| 1283 | .InfixOp => switch (@ptrCast(*const ast.Node.InfixOp, &res.node).op) { |
| 1284 | .BoolOr, |
| 1285 | .BoolAnd, |
| 1286 | .EqualEqual, |
| 1287 | .BangEqual, |
| 1288 | .LessThan, |
| 1289 | .GreaterThan, |
| 1290 | .LessOrEqual, |
| 1291 | .GreaterOrEqual, |
| 1292 | => return res.node, |
| 1293 | |
| 1294 | else => {}, |
| 1295 | }, |
| 1296 | |
| 1297 | .PrefixOp => switch (@ptrCast(*const ast.Node.PrefixOp, &res.node).op) { |
| 1298 | .BoolNot => return res.node, |
| 1299 | |
| 1300 | else => {}, |
| 1301 | }, |
| 1302 | |
| 1303 | .BoolLiteral => return res.node, |
| 1304 | |
| 1305 | else => {}, |
| 1306 | } |
| 1307 | |
| 1308 | const ty = ZigClangQualType_getTypePtr(getExprQualTypeBeforeImplicitCast(rp.c, expr)); |
| 1309 | |
| 1310 | switch (ZigClangType_getTypeClass(ty)) { |
| 1311 | .Builtin => { |
| 1312 | const builtin_ty = @ptrCast(*const ZigClangBuiltinType, ty); |
| 1313 | |
| 1314 | switch (ZigClangBuiltinType_getKind(builtin_ty)) { |
| 1315 | .Bool, |
| 1316 | .Char_U, |
| 1317 | .UChar, |
| 1318 | .Char_S, |
| 1319 | .SChar, |
| 1320 | .UShort, |
| 1321 | .UInt, |
| 1322 | .ULong, |
| 1323 | .ULongLong, |
| 1324 | .Short, |
| 1325 | .Int, |
| 1326 | .Long, |
| 1327 | .LongLong, |
| 1328 | .UInt128, |
| 1329 | .Int128, |
| 1330 | .Float, |
| 1331 | .Double, |
| 1332 | .Float128, |
| 1333 | .LongDouble, |
| 1334 | .WChar_U, |
| 1335 | .Char8, |
| 1336 | .Char16, |
| 1337 | .Char32, |
| 1338 | .WChar_S, |
| 1339 | .Float16, |
| 1340 | => return transCreateNodeNotEqual(rp, scope, res.node, try transCreateNodeInt(rp.c, 0)), |
| 1341 | |
| 1342 | .NullPtr => return transCreateNodeNotEqual(rp, scope, res.node, try transCreateNodeNullLiteral(rp.c)), |
| 1343 | |
| 1344 | .Void, |
| 1345 | .Half, |
| 1346 | .ObjCId, |
| 1347 | .ObjCClass, |
| 1348 | .ObjCSel, |
| 1349 | .OMPArraySection, |
| 1350 | .Dependent, |
| 1351 | .Overload, |
| 1352 | .BoundMember, |
| 1353 | .PseudoObject, |
| 1354 | .UnknownAny, |
| 1355 | .BuiltinFn, |
| 1356 | .ARCUnbridgedCast, |
| 1357 | .OCLImage1dRO, |
| 1358 | .OCLImage1dArrayRO, |
| 1359 | .OCLImage1dBufferRO, |
| 1360 | .OCLImage2dRO, |
| 1361 | .OCLImage2dArrayRO, |
| 1362 | .OCLImage2dDepthRO, |
| 1363 | .OCLImage2dArrayDepthRO, |
| 1364 | .OCLImage2dMSAARO, |
| 1365 | .OCLImage2dArrayMSAARO, |
| 1366 | .OCLImage2dMSAADepthRO, |
| 1367 | .OCLImage2dArrayMSAADepthRO, |
| 1368 | .OCLImage3dRO, |
| 1369 | .OCLImage1dWO, |
| 1370 | .OCLImage1dArrayWO, |
| 1371 | .OCLImage1dBufferWO, |
| 1372 | .OCLImage2dWO, |
| 1373 | .OCLImage2dArrayWO, |
| 1374 | .OCLImage2dDepthWO, |
| 1375 | .OCLImage2dArrayDepthWO, |
| 1376 | .OCLImage2dMSAAWO, |
| 1377 | .OCLImage2dArrayMSAAWO, |
| 1378 | .OCLImage2dMSAADepthWO, |
| 1379 | .OCLImage2dArrayMSAADepthWO, |
| 1380 | .OCLImage3dWO, |
| 1381 | .OCLImage1dRW, |
| 1382 | .OCLImage1dArrayRW, |
| 1383 | .OCLImage1dBufferRW, |
| 1384 | .OCLImage2dRW, |
| 1385 | .OCLImage2dArrayRW, |
| 1386 | .OCLImage2dDepthRW, |
| 1387 | .OCLImage2dArrayDepthRW, |
| 1388 | .OCLImage2dMSAARW, |
| 1389 | .OCLImage2dArrayMSAARW, |
| 1390 | .OCLImage2dMSAADepthRW, |
| 1391 | .OCLImage2dArrayMSAADepthRW, |
| 1392 | .OCLImage3dRW, |
| 1393 | .OCLSampler, |
| 1394 | .OCLEvent, |
| 1395 | .OCLClkEvent, |
| 1396 | .OCLQueue, |
| 1397 | .OCLReserveID, |
| 1398 | .ShortAccum, |
| 1399 | .Accum, |
| 1400 | .LongAccum, |
| 1401 | .UShortAccum, |
| 1402 | .UAccum, |
| 1403 | .ULongAccum, |
| 1404 | .ShortFract, |
| 1405 | .Fract, |
| 1406 | .LongFract, |
| 1407 | .UShortFract, |
| 1408 | .UFract, |
| 1409 | .ULongFract, |
| 1410 | .SatShortAccum, |
| 1411 | .SatAccum, |
| 1412 | .SatLongAccum, |
| 1413 | .SatUShortAccum, |
| 1414 | .SatUAccum, |
| 1415 | .SatULongAccum, |
| 1416 | .SatShortFract, |
| 1417 | .SatFract, |
| 1418 | .SatLongFract, |
| 1419 | .SatUShortFract, |
| 1420 | .SatUFract, |
| 1421 | .SatULongFract, |
| 1422 | .OCLIntelSubgroupAVCMcePayload, |
| 1423 | .OCLIntelSubgroupAVCImePayload, |
| 1424 | .OCLIntelSubgroupAVCRefPayload, |
| 1425 | .OCLIntelSubgroupAVCSicPayload, |
| 1426 | .OCLIntelSubgroupAVCMceResult, |
| 1427 | .OCLIntelSubgroupAVCImeResult, |
| 1428 | .OCLIntelSubgroupAVCRefResult, |
| 1429 | .OCLIntelSubgroupAVCSicResult, |
| 1430 | .OCLIntelSubgroupAVCImeResultSingleRefStreamout, |
| 1431 | .OCLIntelSubgroupAVCImeResultDualRefStreamout, |
| 1432 | .OCLIntelSubgroupAVCImeSingleRefStreamin, |
| 1433 | .OCLIntelSubgroupAVCImeDualRefStreamin, |
| 1434 | => return res.node, |
| 1435 | |
| 1436 | else => {}, |
| 1437 | } |
| 1438 | }, |
| 1439 | .Pointer => return transCreateNodeNotEqual(rp, scope, res.node, try transCreateNodeNullLiteral(rp.c)), |
| 1440 | |
| 1441 | .Typedef => { |
| 1442 | return transCreateNodeNotEqual(rp, scope, res.node, try transCreateNodeInt(rp.c, 0)); // TODO currently assuming it is like an int/char/bool builtin type. Coerce the type and recurse? Add a toTypedefZeroCmp function? |
| 1443 | |
| 1444 | // TODO This is the code that was in translate-c, but it seems like it is giving wrong results! It just prints the typedef name instead of the value |
| 1445 | // const typedef_ty = @ptrCast(*const ZigClangTypedefType, ty); |
| 1446 | // const typedef_decl = ZigClangTypedefType_getDecl(typedef_ty); |
| 1447 | // const typedef_name_decl = ZigClangTypedefNameDecl_getCanonicalDecl(typedef_decl); |
| 1448 | |
| 1449 | // const typedef_name = if (rp.c.decl_table.get(@ptrToInt(typedef_name_decl))) |existing_entry| |
| 1450 | // existing_entry.value |
| 1451 | // else |
| 1452 | // try rp.c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, typedef_name_decl))); |
| 1453 | |
| 1454 | // return transCreateNodeIdentifier(rp.c, typedef_name); |
| 1455 | }, |
| 1456 | |
| 1457 | .Enum => { |
| 1458 | const gen_enum_decl_node = struct { |
| 1459 | // Have to use a callback because node must be generated inline in order to avoid weird AST printing behavior, |
| 1460 | // and the code to generate the nodes is a little different for each case |
| 1461 | fn generate_node(inner_rp: RestorePoint, enum_ty: *const struct_ZigClangType, source_loc: ZigClangSourceLocation) TransError!*ast.Node { |
| 1462 | const actual_enum_ty = @ptrCast(*const ZigClangEnumType, enum_ty); |
| 1463 | const enum_decl = ZigClangEnumType_getDecl(actual_enum_ty); |
| 1464 | const enum_type = (try transEnumDecl(inner_rp.c, enum_decl)) orelse { |
| 1465 | return revertAndWarn(inner_rp, error.UnsupportedType, source_loc, "unable to translate enum declaration", .{}); |
| 1466 | }; |
| 1467 | return enum_type; |
| 1468 | } |
| 1469 | }; |
| 1470 | |
| 1471 | return toEnumZeroCmp(rp, scope, res.node, gen_enum_decl_node.generate_node, ty, ZigClangExpr_getBeginLoc(expr)); |
| 1472 | }, |
| 1473 | |
| 1474 | .Elaborated => { |
| 1475 | const elaborated_ty = @ptrCast(*const ZigClangElaboratedType, ty); |
| 1476 | |
| 1477 | switch (ZigClangElaboratedType_getKeyword(elaborated_ty)) { |
| 1478 | .Enum => { |
| 1479 | // Have to use a callback because node must be generated inline in order to avoid weird AST printing behavior, |
| 1480 | // and the code to generate the nodes is a little different for each case |
| 1481 | const gen_enum_type_node = struct { |
| 1482 | fn generate_node(inner_rp: RestorePoint, enum_ty: *const struct_ZigClangType, source_loc: ZigClangSourceLocation) TransError!*ast.Node { |
| 1483 | const inner_elaborated_ty = @ptrCast(*const ZigClangElaboratedType, enum_ty); |
| 1484 | const enum_type = try transQualType(inner_rp, ZigClangElaboratedType_getNamedType(inner_elaborated_ty), source_loc); |
| 1485 | return enum_type; |
| 1486 | } |
| 1487 | }; |
| 1488 | |
| 1489 | return toEnumZeroCmp(rp, scope, res.node, gen_enum_type_node.generate_node, ty, ZigClangExpr_getBeginLoc(expr)); |
| 1490 | }, |
| 1491 | |
| 1492 | .Struct, |
| 1493 | .Union, |
| 1494 | .Interface, |
| 1495 | .Class, |
| 1496 | .Typename, |
| 1497 | .None, |
| 1498 | => return res.node, |
| 1499 | |
| 1500 | else => {}, |
| 1501 | } |
| 1502 | }, |
| 1503 | |
| 1504 | .FunctionProto, |
| 1505 | .Record, |
| 1506 | .ConstantArray, |
| 1507 | .Paren, |
| 1508 | .Decayed, |
| 1509 | .Attributed, |
| 1510 | .IncompleteArray, |
| 1511 | .BlockPointer, |
| 1512 | .LValueReference, |
| 1513 | .RValueReference, |
| 1514 | .MemberPointer, |
| 1515 | .VariableArray, |
| 1516 | .DependentSizedArray, |
| 1517 | .DependentSizedExtVector, |
| 1518 | .Vector, |
| 1519 | .ExtVector, |
| 1520 | .FunctionNoProto, |
| 1521 | .UnresolvedUsing, |
| 1522 | .Adjusted, |
| 1523 | .TypeOfExpr, |
| 1524 | .TypeOf, |
| 1525 | .Decltype, |
| 1526 | .UnaryTransform, |
| 1527 | .TemplateTypeParm, |
| 1528 | .SubstTemplateTypeParm, |
| 1529 | .SubstTemplateTypeParmPack, |
| 1530 | .TemplateSpecialization, |
| 1531 | .Auto, |
| 1532 | .InjectedClassName, |
| 1533 | .DependentName, |
| 1534 | .DependentTemplateSpecialization, |
| 1535 | .PackExpansion, |
| 1536 | .ObjCObject, |
| 1537 | .ObjCInterface, |
| 1538 | .Complex, |
| 1539 | .ObjCObjectPointer, |
| 1540 | .Atomic, |
| 1541 | .Pipe, |
| 1542 | .ObjCTypeParam, |
| 1543 | .DeducedTemplateSpecialization, |
| 1544 | .DependentAddressSpace, |
| 1545 | .DependentVector, |
| 1546 | .MacroQualified, |
| 1547 | => return res.node, |
| 1548 | |
| 1549 | else => unreachable, |
| 1550 | } |
| 1551 | |
| 1552 | unreachable; |
| 1553 | } |
| 1554 | |
| 1150 | 1555 | fn transIntegerLiteral( |
| 1151 | 1556 | rp: RestorePoint, |
| 1152 | 1557 | scope: *Scope, |
| ... | ... | @@ -1925,6 +2330,95 @@ fn qualTypeIsPtr(qt: ZigClangQualType) bool { |
| 1925 | 2330 | return ZigClangType_getTypeClass(qualTypeCanon(qt)) == .Pointer; |
| 1926 | 2331 | } |
| 1927 | 2332 | |
| 2333 | fn qualTypeIntBitWidth(rp: RestorePoint, qt: ZigClangQualType, source_loc: ZigClangSourceLocation) !u32 { |
| 2334 | const ty = ZigClangQualType_getTypePtr(qt); |
| 2335 | |
| 2336 | switch (ZigClangType_getTypeClass(ty)) { |
| 2337 | .Builtin => { |
| 2338 | const builtin_ty = @ptrCast(*const ZigClangBuiltinType, ty); |
| 2339 | |
| 2340 | switch (ZigClangBuiltinType_getKind(builtin_ty)) { |
| 2341 | .Char_U, |
| 2342 | .UChar, |
| 2343 | .Char_S, |
| 2344 | .SChar, |
| 2345 | => return 8, |
| 2346 | .UInt128, |
| 2347 | .Int128, |
| 2348 | => return 128, |
| 2349 | else => return 0, |
| 2350 | } |
| 2351 | |
| 2352 | unreachable; |
| 2353 | }, |
| 2354 | .Typedef => { |
| 2355 | const typedef_ty = @ptrCast(*const ZigClangTypedefType, ty); |
| 2356 | const typedef_decl = ZigClangTypedefType_getDecl(typedef_ty); |
| 2357 | const type_name = try rp.c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, typedef_decl))); |
| 2358 | |
| 2359 | if (std.mem.eql(u8, type_name, "uint8_t") or std.mem.eql(u8, type_name, "int8_t")) { |
| 2360 | return 8; |
| 2361 | } else if (std.mem.eql(u8, type_name, "uint16_t") or std.mem.eql(u8, type_name, "int16_t")) { |
| 2362 | return 16; |
| 2363 | } else if (std.mem.eql(u8, type_name, "uint32_t") or std.mem.eql(u8, type_name, "int32_t")) { |
| 2364 | return 32; |
| 2365 | } else if (std.mem.eql(u8, type_name, "uint64_t") or std.mem.eql(u8, type_name, "int64_t")) { |
| 2366 | return 64; |
| 2367 | } else { |
| 2368 | return 0; |
| 2369 | } |
| 2370 | }, |
| 2371 | else => return 0, |
| 2372 | } |
| 2373 | |
| 2374 | unreachable; |
| 2375 | } |
| 2376 | |
| 2377 | fn qualTypeToLog2IntRef(rp: RestorePoint, qt: ZigClangQualType, source_loc: ZigClangSourceLocation) !*ast.Node { |
| 2378 | const int_bit_width = try qualTypeIntBitWidth(rp, qt, source_loc); |
| 2379 | |
| 2380 | if (int_bit_width != 0) { |
| 2381 | // we can perform the log2 now. |
| 2382 | const cast_bit_width = std.math.log2_int(u64, int_bit_width); |
| 2383 | const node = try rp.c.a().create(ast.Node.IntegerLiteral); |
| 2384 | node.* = ast.Node.IntegerLiteral{ |
| 2385 | .token = try appendTokenFmt(rp.c, .Identifier, "u{}", .{cast_bit_width}), |
| 2386 | }; |
| 2387 | return &node.base; |
| 2388 | } |
| 2389 | |
| 2390 | const zig_type_node = try transQualType(rp, qt, source_loc); |
| 2391 | |
| 2392 | // @import("std").math.Log2Int(c_long); |
| 2393 | // |
| 2394 | // FnCall |
| 2395 | // FieldAccess |
| 2396 | // FieldAccess |
| 2397 | // FnCall (.builtin = true) |
| 2398 | // Symbol "import" |
| 2399 | // StringLiteral "std" |
| 2400 | // Symbol "math" |
| 2401 | // Symbol "Log2Int" |
| 2402 | // Symbol <zig_type_node> (var from above) |
| 2403 | |
| 2404 | const import_fn_call = try transCreateNodeBuiltinFnCall(rp.c, "@import"); |
| 2405 | const std_token = try appendToken(rp.c, .StringLiteral, "\"std\""); |
| 2406 | const std_node = try rp.c.a().create(ast.Node.StringLiteral); |
| 2407 | std_node.* = ast.Node.StringLiteral{ |
| 2408 | .token = std_token, |
| 2409 | }; |
| 2410 | try import_fn_call.params.push(&std_node.base); |
| 2411 | import_fn_call.rparen_token = try appendToken(rp.c, .RParen, ")"); |
| 2412 | |
| 2413 | const inner_field_access = try transCreateNodeFieldAccess(rp.c, &import_fn_call.base, "math"); |
| 2414 | const outer_field_access = try transCreateNodeFieldAccess(rp.c, &inner_field_access.base, "Log2Int"); |
| 2415 | const log2int_fn_call = try transCreateNodeFnCall(rp.c, &outer_field_access.base); |
| 2416 | try @ptrCast(*ast.Node.SuffixOp.Op.Call, &log2int_fn_call.op).params.push(zig_type_node); |
| 2417 | log2int_fn_call.rtoken = try appendToken(rp.c, .RParen, ")"); |
| 2418 | |
| 2419 | return &log2int_fn_call.base; |
| 2420 | } |
| 2421 | |
| 1928 | 2422 | fn qualTypeChildIsFnProto(qt: ZigClangQualType) bool { |
| 1929 | 2423 | const ty = ZigClangQualType_getTypePtr(qt); |
| 1930 | 2424 | |
| ... | ... | @@ -1974,6 +2468,14 @@ fn getExprQualType(c: *Context, expr: *const ZigClangExpr) ZigClangQualType { |
| 1974 | 2468 | return ZigClangExpr_getType(expr); |
| 1975 | 2469 | } |
| 1976 | 2470 | |
| 2471 | fn getExprQualTypeBeforeImplicitCast(c: *Context, expr: *const ZigClangExpr) ZigClangQualType { |
| 2472 | if (ZigClangExpr_getStmtClass(expr) == .ImplicitCastExprClass) { |
| 2473 | const cast_expr = @ptrCast(*const ZigClangImplicitCastExpr, expr); |
| 2474 | return getExprQualType(c, ZigClangImplicitCastExpr_getSubExpr(cast_expr)); |
| 2475 | } |
| 2476 | return ZigClangExpr_getType(expr); |
| 2477 | } |
| 2478 | |
| 1977 | 2479 | fn typeIsOpaque(c: *Context, ty: *const ZigClangType, loc: ZigClangSourceLocation) bool { |
| 1978 | 2480 | switch (ZigClangType_getTypeClass(ty)) { |
| 1979 | 2481 | .Builtin => { |
| ... | ... | @@ -2142,6 +2644,17 @@ fn transCreateNodeFnCall(c: *Context, fn_expr: *ast.Node) !*ast.Node.SuffixOp { |
| 2142 | 2644 | return node; |
| 2143 | 2645 | } |
| 2144 | 2646 | |
| 2647 | fn transCreateNodeFieldAccess(c: *Context, container: *ast.Node, field_name: []const u8) !*ast.Node.InfixOp { |
| 2648 | const field_access_node = try c.a().create(ast.Node.InfixOp); |
| 2649 | field_access_node.* = .{ |
| 2650 | .op_token = try appendToken(c, .Period, "."), |
| 2651 | .lhs = container, |
| 2652 | .op = .Period, |
| 2653 | .rhs = try transCreateNodeIdentifier(c, field_name), |
| 2654 | }; |
| 2655 | return field_access_node; |
| 2656 | } |
| 2657 | |
| 2145 | 2658 | fn transCreateNodePrefixOp( |
| 2146 | 2659 | c: *Context, |
| 2147 | 2660 | op: ast.Node.PrefixOp.Op, |
| ... | ... | @@ -2157,25 +2670,24 @@ fn transCreateNodePrefixOp( |
| 2157 | 2670 | return node; |
| 2158 | 2671 | } |
| 2159 | 2672 | |
| 2160 | | fn transCreateNodeInfixOp( |
| 2673 | fn transCreateNodeInfixOpImpl( |
| 2161 | 2674 | rp: RestorePoint, |
| 2162 | 2675 | scope: *Scope, |
| 2163 | | stmt: *const ZigClangBinaryOperator, |
| 2676 | lhs_node: *ast.Node, |
| 2677 | rhs_node: *ast.Node, |
| 2164 | 2678 | op: ast.Node.InfixOp.Op, |
| 2165 | 2679 | op_tok_id: std.zig.Token.Id, |
| 2166 | 2680 | bytes: []const u8, |
| 2167 | 2681 | grouped: bool, |
| 2168 | 2682 | ) !*ast.Node { |
| 2169 | 2683 | const lparen = if (grouped) try appendToken(rp.c, .LParen, "(") else undefined; |
| 2170 | | const lhs = try transExpr(rp, scope, ZigClangBinaryOperator_getLHS(stmt), .used, .l_value); |
| 2171 | 2684 | const op_token = try appendToken(rp.c, op_tok_id, bytes); |
| 2172 | | const rhs = try transExpr(rp, scope, ZigClangBinaryOperator_getRHS(stmt), .used, .r_value); |
| 2173 | 2685 | const node = try rp.c.a().create(ast.Node.InfixOp); |
| 2174 | 2686 | node.* = ast.Node.InfixOp{ |
| 2175 | 2687 | .op_token = op_token, |
| 2176 | | .lhs = lhs, |
| 2688 | .lhs = lhs_node, |
| 2177 | 2689 | .op = op, |
| 2178 | | .rhs = rhs, |
| 2690 | .rhs = rhs_node, |
| 2179 | 2691 | }; |
| 2180 | 2692 | if (!grouped) return &node.base; |
| 2181 | 2693 | const rparen = try appendToken(rp.c, .RParen, ")"); |
| ... | ... | @@ -2188,6 +2700,60 @@ fn transCreateNodeInfixOp( |
| 2188 | 2700 | return &grouped_expr.base; |
| 2189 | 2701 | } |
| 2190 | 2702 | |
| 2703 | fn transCreateNodeInfixOp( |
| 2704 | rp: RestorePoint, |
| 2705 | scope: *Scope, |
| 2706 | stmt: *const ZigClangBinaryOperator, |
| 2707 | op: ast.Node.InfixOp.Op, |
| 2708 | op_tok_id: std.zig.Token.Id, |
| 2709 | bytes: []const u8, |
| 2710 | grouped: bool, |
| 2711 | ) !*ast.Node { |
| 2712 | return transCreateNodeInfixOpImpl( |
| 2713 | rp, |
| 2714 | scope, |
| 2715 | (try transExpr(rp, scope, ZigClangBinaryOperator_getLHS(stmt), .used, .r_value)).node, |
| 2716 | (try transExpr(rp, scope, ZigClangBinaryOperator_getRHS(stmt), .used, .r_value)).node, |
| 2717 | op, |
| 2718 | op_tok_id, |
| 2719 | bytes, |
| 2720 | grouped, |
| 2721 | ); |
| 2722 | } |
| 2723 | |
| 2724 | fn transCreateNodeNotEqual( |
| 2725 | rp: RestorePoint, |
| 2726 | scope: *Scope, |
| 2727 | lhs_node: *ast.Node, |
| 2728 | rhs_node: *ast.Node, |
| 2729 | ) !*ast.Node { |
| 2730 | return transCreateNodeInfixOpImpl(rp, scope, lhs_node, rhs_node, .BangEqual, .BangEqual, "!=", true); |
| 2731 | } |
| 2732 | |
| 2733 | fn transCreateNodeBoolInfixOp( |
| 2734 | rp: RestorePoint, |
| 2735 | scope: *Scope, |
| 2736 | stmt: *const ZigClangBinaryOperator, |
| 2737 | comptime op: ast.Node.InfixOp.Op, |
| 2738 | comptime op_tok_id: std.zig.Token.Id, |
| 2739 | comptime bytes: []const u8, |
| 2740 | ) !*ast.Node { |
| 2741 | if (!(op == .BoolAnd or op == .BoolOr)) { |
| 2742 | @compileError("op must be either .BoolAnd or .BoolOr"); |
| 2743 | } |
| 2744 | |
| 2745 | return transCreateNodeInfixOpImpl( |
| 2746 | rp, |
| 2747 | scope, |
| 2748 | try transBoolExpr(rp, scope, ZigClangBinaryOperator_getLHS(stmt), .used, .r_value), |
| 2749 | try transBoolExpr(rp, scope, ZigClangBinaryOperator_getRHS(stmt), .used, .r_value), |
| 2750 | op, |
| 2751 | op_tok_id, |
| 2752 | bytes, |
| 2753 | true, |
| 2754 | ); |
| 2755 | } |
| 2756 | |
| 2191 | 2757 | fn transCreateNodePtrType( |
| 2192 | 2758 | c: *Context, |
| 2193 | 2759 | is_const: bool, |
| ... | ... | @@ -2575,6 +3141,45 @@ fn transCreateNodeSwitchElse(c: *Context) !*ast.Node { |
| 2575 | 3141 | return &node.base; |
| 2576 | 3142 | } |
| 2577 | 3143 | |
| 3144 | fn transCreateNodeShiftOp( |
| 3145 | rp: RestorePoint, |
| 3146 | scope: *Scope, |
| 3147 | stmt: *const ZigClangBinaryOperator, |
| 3148 | comptime op: ast.Node.InfixOp.Op, |
| 3149 | comptime op_tok_id: std.zig.Token.Id, |
| 3150 | comptime bytes: []const u8, |
| 3151 | ) !*ast.Node { |
| 3152 | if (!(op == .BitShiftLeft or op == .BitShiftRight)) { |
| 3153 | @compileError("op must be either .BitShiftLeft or .BitShiftRight"); |
| 3154 | } |
| 3155 | |
| 3156 | const lhs_expr = ZigClangBinaryOperator_getLHS(stmt); |
| 3157 | const rhs_expr = ZigClangBinaryOperator_getRHS(stmt); |
| 3158 | const rhs_location = ZigClangExpr_getBeginLoc(rhs_expr); |
| 3159 | // lhs >> u5(rh) |
| 3160 | |
| 3161 | const lhs = try transExpr(rp, scope, lhs_expr, .used, .r_value); |
| 3162 | const op_token = try appendToken(rp.c, op_tok_id, bytes); |
| 3163 | |
| 3164 | const as_node = try transCreateNodeBuiltinFnCall(rp.c, "@as"); |
| 3165 | const rhs_type = try qualTypeToLog2IntRef(rp, ZigClangBinaryOperator_getType(stmt), rhs_location); |
| 3166 | try as_node.params.push(rhs_type); |
| 3167 | _ = try appendToken(rp.c, .Comma, ","); |
| 3168 | const rhs = try transExpr(rp, scope, rhs_expr, .used, .r_value); |
| 3169 | try as_node.params.push(rhs.node); |
| 3170 | as_node.rparen_token = try appendToken(rp.c, .RParen, ")"); |
| 3171 | |
| 3172 | const node = try rp.c.a().create(ast.Node.InfixOp); |
| 3173 | node.* = ast.Node.InfixOp{ |
| 3174 | .op_token = op_token, |
| 3175 | .lhs = lhs.node, |
| 3176 | .op = op, |
| 3177 | .rhs = &as_node.base, |
| 3178 | }; |
| 3179 | |
| 3180 | return &node.base; |
| 3181 | } |
| 3182 | |
| 2578 | 3183 | const RestorePoint = struct { |
| 2579 | 3184 | c: *Context, |
| 2580 | 3185 | token_index: ast.TokenIndex, |