| ... | @@ -126,6 +126,13 @@ static AstNode *trans_create_node_opaque(Context *c) { | ... | @@ -126,6 +126,13 @@ static AstNode *trans_create_node_opaque(Context *c) { |
| 126 | return trans_create_node_builtin_fn_call_str(c, "OpaqueType"); | 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 | static AstNode *trans_create_node_field_access(Context *c, AstNode *container, Buf *field_name) { | 136 | static AstNode *trans_create_node_field_access(Context *c, AstNode *container, Buf *field_name) { |
| 130 | AstNode *node = trans_create_node(c, NodeTypeFieldAccessExpr); | 137 | AstNode *node = trans_create_node(c, NodeTypeFieldAccessExpr); |
| 131 | node->data.field_access_expr.struct_expr = container; | 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,6 +140,10 @@ static AstNode *trans_create_node_field_access(Context *c, AstNode *container, B |
| 133 | return node; | 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 | static AstNode *trans_create_node_prefix_op(Context *c, PrefixOp op, AstNode *child_node) { | 147 | static AstNode *trans_create_node_prefix_op(Context *c, PrefixOp op, AstNode *child_node) { |
| 137 | AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr); | 148 | AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr); |
| 138 | node->data.prefix_op_expr.prefix_op = op; | 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,6 +151,14 @@ static AstNode *trans_create_node_prefix_op(Context *c, PrefixOp op, AstNode *ch |
| 140 | return node; | 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 | static AstNode *trans_create_node_addr_of(Context *c, bool is_const, bool is_volatile, AstNode *child_node) { | 162 | static AstNode *trans_create_node_addr_of(Context *c, bool is_const, bool is_volatile, AstNode *child_node) { |
| 144 | AstNode *node = trans_create_node(c, NodeTypeAddrOfExpr); | 163 | AstNode *node = trans_create_node(c, NodeTypeAddrOfExpr); |
| 145 | node->data.addr_of_expr.is_const = is_const; | 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,6 +174,13 @@ static AstNode *trans_create_node_str_lit_c(Context *c, Buf *buf) { |
| 155 | return node; | 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 | static AstNode *trans_create_node_unsigned_negative(Context *c, uint64_t x, bool is_negative) { | 184 | static AstNode *trans_create_node_unsigned_negative(Context *c, uint64_t x, bool is_negative) { |
| 159 | AstNode *node = trans_create_node(c, NodeTypeIntLiteral); | 185 | AstNode *node = trans_create_node(c, NodeTypeIntLiteral); |
| 160 | node->data.int_literal.bigint = allocate<BigInt>(1); | 186 | node->data.int_literal.bigint = allocate<BigInt>(1); |
| ... | @@ -286,10 +312,45 @@ static AstNode *trans_create_node_apint(Context *c, const llvm::APSInt &aps_int) | ... | @@ -286,10 +312,45 @@ static AstNode *trans_create_node_apint(Context *c, const llvm::APSInt &aps_int) |
| 286 | | 312 | |
| 287 | } | 313 | } |
| 288 | | 314 | |
| | 315 | static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc); |
| | 316 | |
| 289 | static bool is_c_void_type(AstNode *node) { | 317 | static bool is_c_void_type(AstNode *node) { |
| 290 | return (node->type == NodeTypeSymbol && buf_eql_str(node->data.symbol_expr.symbol, "c_void")); | 318 | return (node->type == NodeTypeSymbol && buf_eql_str(node->data.symbol_expr.symbol, "c_void")); |
| 291 | } | 319 | } |
| 292 | | 320 | |
| | 321 | static AstNode* trans_c_cast(Context *c, const SourceLocation &source_location, const QualType &qt, AstNode *expr) { |
| | 322 | // TODO: maybe widen to increase size |
| | 323 | // TODO: maybe bitcast to change sign |
| | 324 | // TODO: maybe truncate to reduce size |
| | 325 | return trans_create_node_fn_call_1(c, trans_qual_type(c, qt, source_location), expr); |
| | 326 | } |
| | 327 | |
| | 328 | static AstNode *qual_type_to_log2_int_ref(Context *c, const QualType &qt, |
| | 329 | const SourceLocation &source_loc) |
| | 330 | { |
| | 331 | AstNode *zig_type_node = trans_qual_type(c, qt, source_loc); |
| | 332 | |
| | 333 | // @import("std").math.Log2Int(c_long); |
| | 334 | // |
| | 335 | // FnCall |
| | 336 | // FieldAccess |
| | 337 | // FieldAccess |
| | 338 | // FnCall (.builtin = true) |
| | 339 | // Symbol "import" |
| | 340 | // StringLiteral "std" |
| | 341 | // Symbol "math" |
| | 342 | // Symbol "Log2Int" |
| | 343 | // zig_type_node |
| | 344 | |
| | 345 | AstNode *import_fn_call = trans_create_node_builtin_fn_call_str(c, "import"); |
| | 346 | import_fn_call->data.fn_call_expr.params.append(trans_create_node_str_lit_non_c(c, buf_create_from_str("std"))); |
| | 347 | AstNode *inner_field_access = trans_create_node_field_access_str(c, import_fn_call, "math"); |
| | 348 | AstNode *outer_field_access = trans_create_node_field_access_str(c, inner_field_access, "Log2Int"); |
| | 349 | AstNode *log2int_fn_call = trans_create_node_fn_call_1(c, outer_field_access, zig_type_node); |
| | 350 | |
| | 351 | return log2int_fn_call; |
| | 352 | } |
| | 353 | |
| 293 | static bool qual_type_child_is_fn_proto(const QualType &qt) { | 354 | static bool qual_type_child_is_fn_proto(const QualType &qt) { |
| 294 | if (qt.getTypePtr()->getTypeClass() == Type::Paren) { | 355 | if (qt.getTypePtr()->getTypeClass() == Type::Paren) { |
| 295 | const ParenType *paren_type = static_cast<const ParenType *>(qt.getTypePtr()); | 356 | const ParenType *paren_type = static_cast<const ParenType *>(qt.getTypePtr()); |
| ... | @@ -361,7 +422,6 @@ static bool c_is_float(Context *c, QualType qt) { | ... | @@ -361,7 +422,6 @@ static bool c_is_float(Context *c, QualType qt) { |
| 361 | } | 422 | } |
| 362 | | 423 | |
| 363 | static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt); | 424 | static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt); |
| 364 | static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc); | | |
| 365 | static AstNode *const skip_add_to_block_node = (AstNode *) 0x2; | 425 | static AstNode *const skip_add_to_block_node = (AstNode *) 0x2; |
| 366 | | 426 | |
| 367 | static AstNode *trans_expr(Context *c, AstNode *block, Expr *expr) { | 427 | static AstNode *trans_expr(Context *c, AstNode *block, Expr *expr) { |
| ... | @@ -877,25 +937,127 @@ static AstNode *trans_binary_operator(Context *c, AstNode *block, BinaryOperator | ... | @@ -877,25 +937,127 @@ static AstNode *trans_binary_operator(Context *c, AstNode *block, BinaryOperator |
| 877 | zig_unreachable(); | 937 | zig_unreachable(); |
| 878 | } | 938 | } |
| 879 | | 939 | |
| | 940 | static AstNode *trans_compound_assign_operator(Context *c, AstNode *block, CompoundAssignOperator *stmt) { |
| | 941 | switch (stmt->getOpcode()) { |
| | 942 | case BO_MulAssign: |
| | 943 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_MulAssign"); |
| | 944 | return nullptr; |
| | 945 | case BO_DivAssign: |
| | 946 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_DivAssign"); |
| | 947 | return nullptr; |
| | 948 | case BO_RemAssign: |
| | 949 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_RemAssign"); |
| | 950 | return nullptr; |
| | 951 | case BO_AddAssign: |
| | 952 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_AddAssign"); |
| | 953 | return nullptr; |
| | 954 | case BO_SubAssign: |
| | 955 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_SubAssign"); |
| | 956 | return nullptr; |
| | 957 | case BO_ShlAssign: |
| | 958 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_ShlAssign"); |
| | 959 | return nullptr; |
| | 960 | case BO_ShrAssign: { |
| | 961 | BinOpType bin_op = BinOpTypeBitShiftRight; |
| | 962 | // c: lhs >>= rhs; |
| | 963 | // zig: { |
| | 964 | // zig: const _ref = &lhs; |
| | 965 | // zig: *_ref = result_type(operation_type(*_ref) >> u5(rhs)); |
| | 966 | // zig: *_ref |
| | 967 | // zig: }; |
| | 968 | // where u5 is the appropriate type |
| | 969 | |
| | 970 | // TODO: avoid mess when we don't need the assignment value for chained assignments or anything. |
| | 971 | AstNode *child_block = trans_create_node(c, NodeTypeBlock); |
| | 972 | |
| | 973 | // const _ref = &lhs; |
| | 974 | AstNode *lhs = trans_expr(c, child_block, stmt->getLHS()); |
| | 975 | if (lhs == nullptr) return nullptr; |
| | 976 | AstNode *addr_of_lhs = trans_create_node_addr_of(c, false, false, lhs); |
| | 977 | // TODO: avoid name collisions with generated variable names |
| | 978 | Buf* tmp_var_name = buf_create_from_str("_ref"); |
| | 979 | AstNode *tmp_var_decl = trans_create_node_var_decl(c, true, tmp_var_name, nullptr, addr_of_lhs); |
| | 980 | child_block->data.block.statements.append(tmp_var_decl); |
| | 981 | |
| | 982 | // *_ref = result_type(operation_type(*_ref) >> u5(rhs)); |
| | 983 | |
| | 984 | AstNode *rhs = trans_expr(c, child_block, stmt->getRHS()); |
| | 985 | if (rhs == nullptr) return nullptr; |
| | 986 | const SourceLocation &rhs_location = stmt->getRHS()->getLocStart(); |
| | 987 | AstNode *rhs_type = qual_type_to_log2_int_ref(c, stmt->getComputationLHSType(), rhs_location); |
| | 988 | |
| | 989 | AstNode *assign_statement = trans_create_node_bin_op(c, |
| | 990 | trans_create_node_prefix_op(c, PrefixOpDereference, |
| | 991 | trans_create_node_symbol(c, tmp_var_name)), |
| | 992 | BinOpTypeAssign, |
| | 993 | trans_c_cast(c, rhs_location, |
| | 994 | stmt->getComputationResultType(), |
| | 995 | trans_create_node_bin_op(c, |
| | 996 | trans_c_cast(c, rhs_location, |
| | 997 | stmt->getComputationLHSType(), |
| | 998 | trans_create_node_prefix_op(c, PrefixOpDereference, |
| | 999 | trans_create_node_symbol(c, tmp_var_name))), |
| | 1000 | bin_op, |
| | 1001 | trans_create_node_fn_call_1(c, |
| | 1002 | rhs_type, |
| | 1003 | rhs)))); |
| | 1004 | child_block->data.block.statements.append(assign_statement); |
| | 1005 | |
| | 1006 | // *_ref |
| | 1007 | child_block->data.block.statements.append( |
| | 1008 | trans_create_node_prefix_op(c, PrefixOpDereference, |
| | 1009 | trans_create_node_symbol(c, tmp_var_name))); |
| | 1010 | child_block->data.block.last_statement_is_result_expression = true; |
| | 1011 | |
| | 1012 | return child_block; |
| | 1013 | } |
| | 1014 | case BO_AndAssign: |
| | 1015 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_AndAssign"); |
| | 1016 | return nullptr; |
| | 1017 | case BO_XorAssign: |
| | 1018 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_XorAssign"); |
| | 1019 | return nullptr; |
| | 1020 | case BO_OrAssign: |
| | 1021 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_OrAssign"); |
| | 1022 | return nullptr; |
| | 1023 | case BO_PtrMemD: |
| | 1024 | case BO_PtrMemI: |
| | 1025 | case BO_Assign: |
| | 1026 | case BO_Mul: |
| | 1027 | case BO_Div: |
| | 1028 | case BO_Rem: |
| | 1029 | case BO_Add: |
| | 1030 | case BO_Sub: |
| | 1031 | case BO_Shl: |
| | 1032 | case BO_Shr: |
| | 1033 | case BO_LT: |
| | 1034 | case BO_GT: |
| | 1035 | case BO_LE: |
| | 1036 | case BO_GE: |
| | 1037 | case BO_EQ: |
| | 1038 | case BO_NE: |
| | 1039 | case BO_And: |
| | 1040 | case BO_Xor: |
| | 1041 | case BO_Or: |
| | 1042 | case BO_LAnd: |
| | 1043 | case BO_LOr: |
| | 1044 | case BO_Comma: |
| | 1045 | zig_panic("compound assign expected to be handled by binary operator"); |
| | 1046 | } |
| | 1047 | |
| | 1048 | zig_unreachable(); |
| | 1049 | } |
| | 1050 | |
| 880 | static AstNode *trans_implicit_cast_expr(Context *c, AstNode *block, ImplicitCastExpr *stmt) { | 1051 | static AstNode *trans_implicit_cast_expr(Context *c, AstNode *block, ImplicitCastExpr *stmt) { |
| 881 | switch (stmt->getCastKind()) { | 1052 | switch (stmt->getCastKind()) { |
| 882 | case CK_LValueToRValue: | 1053 | case CK_LValueToRValue: |
| 883 | return trans_expr(c, block, stmt->getSubExpr()); | 1054 | return trans_expr(c, block, stmt->getSubExpr()); |
| 884 | case CK_IntegralCast: | 1055 | case CK_IntegralCast: |
| 885 | { | 1056 | { |
| 886 | AstNode *node = trans_create_node_builtin_fn_call_str(c, "bitCast"); | | |
| 887 | | | |
| 888 | AstNode *result_type_node = trans_qual_type(c, stmt->getType(), stmt->getExprLoc()); | | |
| 889 | if (result_type_node == nullptr) | | |
| 890 | return nullptr; | | |
| 891 | | | |
| 892 | AstNode *target_node = trans_expr(c, block, stmt->getSubExpr()); | 1057 | AstNode *target_node = trans_expr(c, block, stmt->getSubExpr()); |
| 893 | if (target_node == nullptr) | 1058 | if (target_node == nullptr) |
| 894 | return nullptr; | 1059 | return nullptr; |
| 895 | | 1060 | return trans_c_cast(c, stmt->getExprLoc(), stmt->getType(), target_node); |
| 896 | node->data.fn_call_expr.params.append(result_type_node); | | |
| 897 | node->data.fn_call_expr.params.append(target_node); | | |
| 898 | return node; | | |
| 899 | } | 1061 | } |
| 900 | case CK_Dependent: | 1062 | case CK_Dependent: |
| 901 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_Dependent"); | 1063 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_Dependent"); |
| ... | @@ -1422,6 +1584,8 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) { | ... | @@ -1422,6 +1584,8 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) { |
| 1422 | return trans_conditional_operator(c, block, (ConditionalOperator *)stmt); | 1584 | return trans_conditional_operator(c, block, (ConditionalOperator *)stmt); |
| 1423 | case Stmt::BinaryOperatorClass: | 1585 | case Stmt::BinaryOperatorClass: |
| 1424 | return trans_binary_operator(c, block, (BinaryOperator *)stmt); | 1586 | return trans_binary_operator(c, block, (BinaryOperator *)stmt); |
| | 1587 | case Stmt::CompoundAssignOperatorClass: |
| | 1588 | return trans_compound_assign_operator(c, block, (CompoundAssignOperator *)stmt); |
| 1425 | case Stmt::ImplicitCastExprClass: | 1589 | case Stmt::ImplicitCastExprClass: |
| 1426 | return trans_implicit_cast_expr(c, block, (ImplicitCastExpr *)stmt); | 1590 | return trans_implicit_cast_expr(c, block, (ImplicitCastExpr *)stmt); |
| 1427 | case Stmt::DeclRefExprClass: | 1591 | case Stmt::DeclRefExprClass: |
| ... | @@ -1504,9 +1668,6 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) { | ... | @@ -1504,9 +1668,6 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) { |
| 1504 | case Stmt::AtomicExprClass: | 1668 | case Stmt::AtomicExprClass: |
| 1505 | emit_warning(c, stmt->getLocStart(), "TODO handle C AtomicExprClass"); | 1669 | emit_warning(c, stmt->getLocStart(), "TODO handle C AtomicExprClass"); |
| 1506 | return nullptr; | 1670 | return nullptr; |
| 1507 | case Stmt::CompoundAssignOperatorClass: | | |
| 1508 | emit_warning(c, stmt->getLocStart(), "TODO handle C CompoundAssignOperatorClass"); | | |
| 1509 | return nullptr; | | |
| 1510 | case Stmt::BlockExprClass: | 1671 | case Stmt::BlockExprClass: |
| 1511 | emit_warning(c, stmt->getLocStart(), "TODO handle C BlockExprClass"); | 1672 | emit_warning(c, stmt->getLocStart(), "TODO handle C BlockExprClass"); |
| 1512 | return nullptr; | 1673 | return nullptr; |