| ... | ... | @@ -126,6 +126,13 @@ static AstNode *trans_create_node_opaque(Context *c) { |
| 126 | 126 | return trans_create_node_builtin_fn_call_str(c, "OpaqueType"); |
| 127 | 127 | } |
| 128 | 128 | |
| 129 | static AstNode *trans_create_node_fn_call_1(Context *c, AstNode *fn_ref_expr, AstNode *arg1) { |
| 130 | AstNode *node = trans_create_node(c, NodeTypeFnCallExpr); |
| 131 | node->data.fn_call_expr.fn_ref_expr = fn_ref_expr; |
| 132 | node->data.fn_call_expr.params.append(arg1); |
| 133 | return node; |
| 134 | } |
| 135 | |
| 129 | 136 | static AstNode *trans_create_node_field_access(Context *c, AstNode *container, Buf *field_name) { |
| 130 | 137 | AstNode *node = trans_create_node(c, NodeTypeFieldAccessExpr); |
| 131 | 138 | node->data.field_access_expr.struct_expr = container; |
| ... | ... | @@ -133,6 +140,10 @@ static AstNode *trans_create_node_field_access(Context *c, AstNode *container, B |
| 133 | 140 | return node; |
| 134 | 141 | } |
| 135 | 142 | |
| 143 | static AstNode *trans_create_node_field_access_str(Context *c, AstNode *container, const char *field_name) { |
| 144 | return trans_create_node_field_access(c, container, buf_create_from_str(field_name)); |
| 145 | } |
| 146 | |
| 136 | 147 | static AstNode *trans_create_node_prefix_op(Context *c, PrefixOp op, AstNode *child_node) { |
| 137 | 148 | AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr); |
| 138 | 149 | node->data.prefix_op_expr.prefix_op = op; |
| ... | ... | @@ -140,6 +151,14 @@ static AstNode *trans_create_node_prefix_op(Context *c, PrefixOp op, AstNode *ch |
| 140 | 151 | return node; |
| 141 | 152 | } |
| 142 | 153 | |
| 154 | static AstNode *trans_create_node_bin_op(Context *c, AstNode *lhs_node, BinOpType op, AstNode *rhs_node) { |
| 155 | AstNode *node = trans_create_node(c, NodeTypeBinOpExpr); |
| 156 | node->data.bin_op_expr.op1 = lhs_node; |
| 157 | node->data.bin_op_expr.bin_op = op; |
| 158 | node->data.bin_op_expr.op2 = rhs_node; |
| 159 | return node; |
| 160 | } |
| 161 | |
| 143 | 162 | static AstNode *trans_create_node_addr_of(Context *c, bool is_const, bool is_volatile, AstNode *child_node) { |
| 144 | 163 | AstNode *node = trans_create_node(c, NodeTypeAddrOfExpr); |
| 145 | 164 | node->data.addr_of_expr.is_const = is_const; |
| ... | ... | @@ -155,6 +174,13 @@ static AstNode *trans_create_node_str_lit_c(Context *c, Buf *buf) { |
| 155 | 174 | return node; |
| 156 | 175 | } |
| 157 | 176 | |
| 177 | static AstNode *trans_create_node_str_lit_non_c(Context *c, Buf *buf) { |
| 178 | AstNode *node = trans_create_node(c, NodeTypeStringLiteral); |
| 179 | node->data.string_literal.buf = buf; |
| 180 | node->data.string_literal.c = false; |
| 181 | return node; |
| 182 | } |
| 183 | |
| 158 | 184 | static AstNode *trans_create_node_unsigned_negative(Context *c, uint64_t x, bool is_negative) { |
| 159 | 185 | AstNode *node = trans_create_node(c, NodeTypeIntLiteral); |
| 160 | 186 | node->data.int_literal.bigint = allocate<BigInt>(1); |
| ... | ... | @@ -298,10 +324,45 @@ static AstNode *trans_create_node_apint(Context *c, const llvm::APSInt &aps_int) |
| 298 | 324 | |
| 299 | 325 | } |
| 300 | 326 | |
| 327 | static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc); |
| 328 | |
| 301 | 329 | static bool is_c_void_type(AstNode *node) { |
| 302 | 330 | return (node->type == NodeTypeSymbol && buf_eql_str(node->data.symbol_expr.symbol, "c_void")); |
| 303 | 331 | } |
| 304 | 332 | |
| 333 | static AstNode* trans_c_cast(Context *c, const SourceLocation &source_location, const QualType &qt, AstNode *expr) { |
| 334 | // TODO: maybe widen to increase size |
| 335 | // TODO: maybe bitcast to change sign |
| 336 | // TODO: maybe truncate to reduce size |
| 337 | return trans_create_node_fn_call_1(c, trans_qual_type(c, qt, source_location), expr); |
| 338 | } |
| 339 | |
| 340 | static AstNode *qual_type_to_log2_int_ref(Context *c, const QualType &qt, |
| 341 | const SourceLocation &source_loc) |
| 342 | { |
| 343 | AstNode *zig_type_node = trans_qual_type(c, qt, source_loc); |
| 344 | |
| 345 | // @import("std").math.Log2Int(c_long); |
| 346 | // |
| 347 | // FnCall |
| 348 | // FieldAccess |
| 349 | // FieldAccess |
| 350 | // FnCall (.builtin = true) |
| 351 | // Symbol "import" |
| 352 | // StringLiteral "std" |
| 353 | // Symbol "math" |
| 354 | // Symbol "Log2Int" |
| 355 | // zig_type_node |
| 356 | |
| 357 | AstNode *import_fn_call = trans_create_node_builtin_fn_call_str(c, "import"); |
| 358 | import_fn_call->data.fn_call_expr.params.append(trans_create_node_str_lit_non_c(c, buf_create_from_str("std"))); |
| 359 | AstNode *inner_field_access = trans_create_node_field_access_str(c, import_fn_call, "math"); |
| 360 | AstNode *outer_field_access = trans_create_node_field_access_str(c, inner_field_access, "Log2Int"); |
| 361 | AstNode *log2int_fn_call = trans_create_node_fn_call_1(c, outer_field_access, zig_type_node); |
| 362 | |
| 363 | return log2int_fn_call; |
| 364 | } |
| 365 | |
| 305 | 366 | static bool qual_type_child_is_fn_proto(const QualType &qt) { |
| 306 | 367 | if (qt.getTypePtr()->getTypeClass() == Type::Paren) { |
| 307 | 368 | const ParenType *paren_type = static_cast<const ParenType *>(qt.getTypePtr()); |
| ... | ... | @@ -373,7 +434,6 @@ static bool c_is_float(Context *c, QualType qt) { |
| 373 | 434 | } |
| 374 | 435 | |
| 375 | 436 | static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt); |
| 376 | | static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc); |
| 377 | 437 | static AstNode *const skip_add_to_block_node = (AstNode *) 0x2; |
| 378 | 438 | |
| 379 | 439 | static AstNode *trans_expr(Context *c, AstNode *block, Expr *expr) { |
| ... | ... | @@ -889,25 +949,127 @@ static AstNode *trans_binary_operator(Context *c, AstNode *block, BinaryOperator |
| 889 | 949 | zig_unreachable(); |
| 890 | 950 | } |
| 891 | 951 | |
| 952 | static AstNode *trans_compound_assign_operator(Context *c, AstNode *block, CompoundAssignOperator *stmt) { |
| 953 | switch (stmt->getOpcode()) { |
| 954 | case BO_MulAssign: |
| 955 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_MulAssign"); |
| 956 | return nullptr; |
| 957 | case BO_DivAssign: |
| 958 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_DivAssign"); |
| 959 | return nullptr; |
| 960 | case BO_RemAssign: |
| 961 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_RemAssign"); |
| 962 | return nullptr; |
| 963 | case BO_AddAssign: |
| 964 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_AddAssign"); |
| 965 | return nullptr; |
| 966 | case BO_SubAssign: |
| 967 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_SubAssign"); |
| 968 | return nullptr; |
| 969 | case BO_ShlAssign: |
| 970 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_ShlAssign"); |
| 971 | return nullptr; |
| 972 | case BO_ShrAssign: { |
| 973 | BinOpType bin_op = BinOpTypeBitShiftRight; |
| 974 | // c: lhs >>= rhs; |
| 975 | // zig: { |
| 976 | // zig: const _ref = &lhs; |
| 977 | // zig: *_ref = result_type(operation_type(*_ref) >> u5(rhs)); |
| 978 | // zig: *_ref |
| 979 | // zig: }; |
| 980 | // where u5 is the appropriate type |
| 981 | |
| 982 | // TODO: avoid mess when we don't need the assignment value for chained assignments or anything. |
| 983 | AstNode *child_block = trans_create_node(c, NodeTypeBlock); |
| 984 | |
| 985 | // const _ref = &lhs; |
| 986 | AstNode *lhs = trans_expr(c, child_block, stmt->getLHS()); |
| 987 | if (lhs == nullptr) return nullptr; |
| 988 | AstNode *addr_of_lhs = trans_create_node_addr_of(c, false, false, lhs); |
| 989 | // TODO: avoid name collisions with generated variable names |
| 990 | Buf* tmp_var_name = buf_create_from_str("_ref"); |
| 991 | AstNode *tmp_var_decl = trans_create_node_var_decl(c, true, tmp_var_name, nullptr, addr_of_lhs); |
| 992 | child_block->data.block.statements.append(tmp_var_decl); |
| 993 | |
| 994 | // *_ref = result_type(operation_type(*_ref) >> u5(rhs)); |
| 995 | |
| 996 | AstNode *rhs = trans_expr(c, child_block, stmt->getRHS()); |
| 997 | if (rhs == nullptr) return nullptr; |
| 998 | const SourceLocation &rhs_location = stmt->getRHS()->getLocStart(); |
| 999 | AstNode *rhs_type = qual_type_to_log2_int_ref(c, stmt->getComputationLHSType(), rhs_location); |
| 1000 | |
| 1001 | AstNode *assign_statement = trans_create_node_bin_op(c, |
| 1002 | trans_create_node_prefix_op(c, PrefixOpDereference, |
| 1003 | trans_create_node_symbol(c, tmp_var_name)), |
| 1004 | BinOpTypeAssign, |
| 1005 | trans_c_cast(c, rhs_location, |
| 1006 | stmt->getComputationResultType(), |
| 1007 | trans_create_node_bin_op(c, |
| 1008 | trans_c_cast(c, rhs_location, |
| 1009 | stmt->getComputationLHSType(), |
| 1010 | trans_create_node_prefix_op(c, PrefixOpDereference, |
| 1011 | trans_create_node_symbol(c, tmp_var_name))), |
| 1012 | bin_op, |
| 1013 | trans_create_node_fn_call_1(c, |
| 1014 | rhs_type, |
| 1015 | rhs)))); |
| 1016 | child_block->data.block.statements.append(assign_statement); |
| 1017 | |
| 1018 | // *_ref |
| 1019 | child_block->data.block.statements.append( |
| 1020 | trans_create_node_prefix_op(c, PrefixOpDereference, |
| 1021 | trans_create_node_symbol(c, tmp_var_name))); |
| 1022 | child_block->data.block.last_statement_is_result_expression = true; |
| 1023 | |
| 1024 | return child_block; |
| 1025 | } |
| 1026 | case BO_AndAssign: |
| 1027 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_AndAssign"); |
| 1028 | return nullptr; |
| 1029 | case BO_XorAssign: |
| 1030 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_XorAssign"); |
| 1031 | return nullptr; |
| 1032 | case BO_OrAssign: |
| 1033 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_OrAssign"); |
| 1034 | return nullptr; |
| 1035 | case BO_PtrMemD: |
| 1036 | case BO_PtrMemI: |
| 1037 | case BO_Assign: |
| 1038 | case BO_Mul: |
| 1039 | case BO_Div: |
| 1040 | case BO_Rem: |
| 1041 | case BO_Add: |
| 1042 | case BO_Sub: |
| 1043 | case BO_Shl: |
| 1044 | case BO_Shr: |
| 1045 | case BO_LT: |
| 1046 | case BO_GT: |
| 1047 | case BO_LE: |
| 1048 | case BO_GE: |
| 1049 | case BO_EQ: |
| 1050 | case BO_NE: |
| 1051 | case BO_And: |
| 1052 | case BO_Xor: |
| 1053 | case BO_Or: |
| 1054 | case BO_LAnd: |
| 1055 | case BO_LOr: |
| 1056 | case BO_Comma: |
| 1057 | zig_panic("compound assign expected to be handled by binary operator"); |
| 1058 | } |
| 1059 | |
| 1060 | zig_unreachable(); |
| 1061 | } |
| 1062 | |
| 892 | 1063 | static AstNode *trans_implicit_cast_expr(Context *c, AstNode *block, ImplicitCastExpr *stmt) { |
| 893 | 1064 | switch (stmt->getCastKind()) { |
| 894 | 1065 | case CK_LValueToRValue: |
| 895 | 1066 | return trans_expr(c, block, stmt->getSubExpr()); |
| 896 | 1067 | case CK_IntegralCast: |
| 897 | 1068 | { |
| 898 | | AstNode *node = trans_create_node_builtin_fn_call_str(c, "bitCast"); |
| 899 | | |
| 900 | | AstNode *result_type_node = trans_qual_type(c, stmt->getType(), stmt->getExprLoc()); |
| 901 | | if (result_type_node == nullptr) |
| 902 | | return nullptr; |
| 903 | | |
| 904 | 1069 | AstNode *target_node = trans_expr(c, block, stmt->getSubExpr()); |
| 905 | 1070 | if (target_node == nullptr) |
| 906 | 1071 | return nullptr; |
| 907 | | |
| 908 | | node->data.fn_call_expr.params.append(result_type_node); |
| 909 | | node->data.fn_call_expr.params.append(target_node); |
| 910 | | return node; |
| 1072 | return trans_c_cast(c, stmt->getExprLoc(), stmt->getType(), target_node); |
| 911 | 1073 | } |
| 912 | 1074 | case CK_Dependent: |
| 913 | 1075 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_Dependent"); |
| ... | ... | @@ -1434,6 +1596,8 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) { |
| 1434 | 1596 | return trans_conditional_operator(c, block, (ConditionalOperator *)stmt); |
| 1435 | 1597 | case Stmt::BinaryOperatorClass: |
| 1436 | 1598 | return trans_binary_operator(c, block, (BinaryOperator *)stmt); |
| 1599 | case Stmt::CompoundAssignOperatorClass: |
| 1600 | return trans_compound_assign_operator(c, block, (CompoundAssignOperator *)stmt); |
| 1437 | 1601 | case Stmt::ImplicitCastExprClass: |
| 1438 | 1602 | return trans_implicit_cast_expr(c, block, (ImplicitCastExpr *)stmt); |
| 1439 | 1603 | case Stmt::DeclRefExprClass: |
| ... | ... | @@ -1516,9 +1680,6 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) { |
| 1516 | 1680 | case Stmt::AtomicExprClass: |
| 1517 | 1681 | emit_warning(c, stmt->getLocStart(), "TODO handle C AtomicExprClass"); |
| 1518 | 1682 | return nullptr; |
| 1519 | | case Stmt::CompoundAssignOperatorClass: |
| 1520 | | emit_warning(c, stmt->getLocStart(), "TODO handle C CompoundAssignOperatorClass"); |
| 1521 | | return nullptr; |
| 1522 | 1683 | case Stmt::BlockExprClass: |
| 1523 | 1684 | emit_warning(c, stmt->getLocStart(), "TODO handle C BlockExprClass"); |
| 1524 | 1685 | return nullptr; |