| ... | @@ -943,26 +943,110 @@ fn transBinaryOperator( | ... | @@ -943,26 +943,110 @@ fn transBinaryOperator( |
| 943 | return maybeSuppressResult(rp, scope, result_used, node); | 943 | return maybeSuppressResult(rp, scope, result_used, node); |
| 944 | } | 944 | } |
| 945 | }, | 945 | }, |
| 946 | .Shl, | 946 | .Shl => { |
| 947 | .Shr, | 947 | const node = try transCreateNodeShiftOp(rp, scope, stmt, .BitShiftLeft, .AngleBracketAngleBracketLeft, "<<"); |
| 948 | .LT, | 948 | return maybeSuppressResult(rp, scope, result_used, TransResult{ |
| 949 | .GT, | 949 | .node = node, |
| 950 | .LE, | 950 | .child_scope = scope, |
| 951 | .GE, | 951 | .node_scope = scope, |
| 952 | .EQ, | 952 | }); |
| 953 | .NE, | 953 | }, |
| 954 | .And, | 954 | .Shr => { |
| 955 | .Xor, | 955 | const node = try transCreateNodeShiftOp(rp, scope, stmt, .BitShiftRight, .AngleBracketAngleBracketRight, ">>"); |
| 956 | .Or, | 956 | return maybeSuppressResult(rp, scope, result_used, TransResult{ |
| 957 | .LAnd, | 957 | .node = node, |
| 958 | .LOr, | 958 | .child_scope = scope, |
| 959 | => return revertAndWarn( | 959 | .node_scope = scope, |
| 960 | rp, | 960 | }); |
| 961 | error.UnsupportedTranslation, | 961 | }, |
| 962 | ZigClangBinaryOperator_getBeginLoc(stmt), | 962 | .LT => { |
| 963 | "TODO: handle more C binary operators: {}", | 963 | const node = try transCreateNodeInfixOp(rp, scope, stmt, .LessThan, .AngleBracketLeft, "<", true); |
| 964 | .{op}, | 964 | return maybeSuppressResult(rp, scope, result_used, TransResult{ |
| 965 | ), | 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 | .Comma => { | 1050 | .Comma => { |
| 967 | const block_scope = try scope.findBlockScope(rp.c); | 1051 | const block_scope = try scope.findBlockScope(rp.c); |
| 968 | const expr = block_scope.base.parent == scope; | 1052 | const expr = block_scope.base.parent == scope; |
| ... | @@ -1147,6 +1231,327 @@ fn transImplicitCastExpr( | ... | @@ -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 | fn transIntegerLiteral( | 1555 | fn transIntegerLiteral( |
| 1151 | rp: RestorePoint, | 1556 | rp: RestorePoint, |
| 1152 | scope: *Scope, | 1557 | scope: *Scope, |
| ... | @@ -1925,6 +2330,95 @@ fn qualTypeIsPtr(qt: ZigClangQualType) bool { | ... | @@ -1925,6 +2330,95 @@ fn qualTypeIsPtr(qt: ZigClangQualType) bool { |
| 1925 | return ZigClangType_getTypeClass(qualTypeCanon(qt)) == .Pointer; | 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 | fn qualTypeChildIsFnProto(qt: ZigClangQualType) bool { | 2422 | fn qualTypeChildIsFnProto(qt: ZigClangQualType) bool { |
| 1929 | const ty = ZigClangQualType_getTypePtr(qt); | 2423 | const ty = ZigClangQualType_getTypePtr(qt); |
| 1930 | | 2424 | |
| ... | @@ -1974,6 +2468,14 @@ fn getExprQualType(c: *Context, expr: *const ZigClangExpr) ZigClangQualType { | ... | @@ -1974,6 +2468,14 @@ fn getExprQualType(c: *Context, expr: *const ZigClangExpr) ZigClangQualType { |
| 1974 | return ZigClangExpr_getType(expr); | 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 | fn typeIsOpaque(c: *Context, ty: *const ZigClangType, loc: ZigClangSourceLocation) bool { | 2479 | fn typeIsOpaque(c: *Context, ty: *const ZigClangType, loc: ZigClangSourceLocation) bool { |
| 1978 | switch (ZigClangType_getTypeClass(ty)) { | 2480 | switch (ZigClangType_getTypeClass(ty)) { |
| 1979 | .Builtin => { | 2481 | .Builtin => { |
| ... | @@ -2142,6 +2644,17 @@ fn transCreateNodeFnCall(c: *Context, fn_expr: *ast.Node) !*ast.Node.SuffixOp { | ... | @@ -2142,6 +2644,17 @@ fn transCreateNodeFnCall(c: *Context, fn_expr: *ast.Node) !*ast.Node.SuffixOp { |
| 2142 | return node; | 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 | fn transCreateNodePrefixOp( | 2658 | fn transCreateNodePrefixOp( |
| 2146 | c: *Context, | 2659 | c: *Context, |
| 2147 | op: ast.Node.PrefixOp.Op, | 2660 | op: ast.Node.PrefixOp.Op, |
| ... | @@ -2157,25 +2670,24 @@ fn transCreateNodePrefixOp( | ... | @@ -2157,25 +2670,24 @@ fn transCreateNodePrefixOp( |
| 2157 | return node; | 2670 | return node; |
| 2158 | } | 2671 | } |
| 2159 | | 2672 | |
| 2160 | fn transCreateNodeInfixOp( | 2673 | fn transCreateNodeInfixOpImpl( |
| 2161 | rp: RestorePoint, | 2674 | rp: RestorePoint, |
| 2162 | scope: *Scope, | 2675 | scope: *Scope, |
| 2163 | stmt: *const ZigClangBinaryOperator, | 2676 | lhs_node: *ast.Node, |
| | 2677 | rhs_node: *ast.Node, |
| 2164 | op: ast.Node.InfixOp.Op, | 2678 | op: ast.Node.InfixOp.Op, |
| 2165 | op_tok_id: std.zig.Token.Id, | 2679 | op_tok_id: std.zig.Token.Id, |
| 2166 | bytes: []const u8, | 2680 | bytes: []const u8, |
| 2167 | grouped: bool, | 2681 | grouped: bool, |
| 2168 | ) !*ast.Node { | 2682 | ) !*ast.Node { |
| 2169 | const lparen = if (grouped) try appendToken(rp.c, .LParen, "(") else undefined; | 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 | const op_token = try appendToken(rp.c, op_tok_id, bytes); | 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 | const node = try rp.c.a().create(ast.Node.InfixOp); | 2685 | const node = try rp.c.a().create(ast.Node.InfixOp); |
| 2174 | node.* = ast.Node.InfixOp{ | 2686 | node.* = ast.Node.InfixOp{ |
| 2175 | .op_token = op_token, | 2687 | .op_token = op_token, |
| 2176 | .lhs = lhs, | 2688 | .lhs = lhs_node, |
| 2177 | .op = op, | 2689 | .op = op, |
| 2178 | .rhs = rhs, | 2690 | .rhs = rhs_node, |
| 2179 | }; | 2691 | }; |
| 2180 | if (!grouped) return &node.base; | 2692 | if (!grouped) return &node.base; |
| 2181 | const rparen = try appendToken(rp.c, .RParen, ")"); | 2693 | const rparen = try appendToken(rp.c, .RParen, ")"); |
| ... | @@ -2188,6 +2700,60 @@ fn transCreateNodeInfixOp( | ... | @@ -2188,6 +2700,60 @@ fn transCreateNodeInfixOp( |
| 2188 | return &grouped_expr.base; | 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 | fn transCreateNodePtrType( | 2757 | fn transCreateNodePtrType( |
| 2192 | c: *Context, | 2758 | c: *Context, |
| 2193 | is_const: bool, | 2759 | is_const: bool, |
| ... | @@ -2575,6 +3141,45 @@ fn transCreateNodeSwitchElse(c: *Context) !*ast.Node { | ... | @@ -2575,6 +3141,45 @@ fn transCreateNodeSwitchElse(c: *Context) !*ast.Node { |
| 2575 | return &node.base; | 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 | const RestorePoint = struct { | 3183 | const RestorePoint = struct { |
| 2579 | c: *Context, | 3184 | c: *Context, |
| 2580 | token_index: ast.TokenIndex, | 3185 | token_index: ast.TokenIndex, |