| ... | ... | @@ -23,6 +23,8 @@ |
| 23 | 23 | |
| 24 | 24 | using namespace clang; |
| 25 | 25 | |
| 26 | struct TransScope; |
| 27 | |
| 26 | 28 | struct MacroSymbol { |
| 27 | 29 | Buf *name; |
| 28 | 30 | Buf *value; |
| ... | ... | @@ -52,12 +54,59 @@ struct Context { |
| 52 | 54 | ASTContext *ctx; |
| 53 | 55 | |
| 54 | 56 | HashMap<Buf *, bool, buf_hash, buf_eql_buf> ptr_params; |
| 57 | TransScope *child_scope; // TODO refactor out |
| 58 | }; |
| 59 | |
| 60 | enum ResultUsed { |
| 61 | ResultUsedNo, |
| 62 | ResultUsedYes, |
| 63 | }; |
| 64 | |
| 65 | enum TransLRValue { |
| 66 | TransLValue, |
| 67 | TransRValue, |
| 68 | }; |
| 69 | |
| 70 | enum TransScopeId { |
| 71 | TransScopeIdSwitch, |
| 72 | TransScopeIdVar, |
| 73 | TransScopeIdBlock, |
| 55 | 74 | }; |
| 56 | 75 | |
| 76 | struct TransScope { |
| 77 | TransScopeId id; |
| 78 | TransScope *parent; |
| 79 | }; |
| 80 | |
| 81 | struct TransScopeSwitch { |
| 82 | TransScope base; |
| 83 | AstNode *switch_node; |
| 84 | }; |
| 85 | |
| 86 | struct TransScopeVar { |
| 87 | TransScope base; |
| 88 | Buf *c_name; |
| 89 | Buf *zig_name; |
| 90 | }; |
| 91 | |
| 92 | struct TransScopeBlock { |
| 93 | TransScope base; |
| 94 | AstNode *node; |
| 95 | }; |
| 96 | |
| 97 | static AstNode *const skip_add_to_block_node = (AstNode *) 0x2; |
| 98 | |
| 99 | static TransScopeBlock *trans_scope_block_create(Context *c, TransScope *parent_scope); |
| 100 | static TransScopeVar *trans_scope_var_create(Context *c, TransScope *parent_scope, Buf *wanted_name); |
| 101 | //static TransScopeSwitch *trans_scope_switch_create(Context *c, TransScope *parent_scope); |
| 102 | |
| 57 | 103 | static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl); |
| 58 | 104 | static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl); |
| 59 | 105 | static AstNode *resolve_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl); |
| 60 | 106 | |
| 107 | static AstNode *trans_stmt(Context *c, ResultUsed result_used, TransScope *scope, const Stmt *stmt, TransLRValue lrval); |
| 108 | static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc); |
| 109 | |
| 61 | 110 | |
| 62 | 111 | ATTRIBUTE_PRINTF(3, 4) |
| 63 | 112 | static void emit_warning(Context *c, const SourceLocation &sl, const char *format, ...) { |
| ... | ... | @@ -165,8 +214,8 @@ static AstNode *trans_create_node_bin_op(Context *c, AstNode *lhs_node, BinOpTyp |
| 165 | 214 | return node; |
| 166 | 215 | } |
| 167 | 216 | |
| 168 | | static AstNode *maybe_suppress_result(Context *c, bool result_used, AstNode *node) { |
| 169 | | if (result_used) return node; |
| 217 | static AstNode *maybe_suppress_result(Context *c, ResultUsed result_used, AstNode *node) { |
| 218 | if (result_used == ResultUsedYes) return node; |
| 170 | 219 | return trans_create_node_bin_op(c, |
| 171 | 220 | trans_create_node_symbol_str(c, "_"), |
| 172 | 221 | BinOpTypeAssign, |
| ... | ... | @@ -341,8 +390,6 @@ static AstNode *trans_create_node_apint(Context *c, const llvm::APSInt &aps_int) |
| 341 | 390 | |
| 342 | 391 | } |
| 343 | 392 | |
| 344 | | static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc); |
| 345 | | |
| 346 | 393 | static QualType get_expr_qual_type(Context *c, const Expr *expr) { |
| 347 | 394 | // String literals in C are `char *` but they should really be `const char *`. |
| 348 | 395 | if (expr->getStmtClass() == Stmt::ImplicitCastExprClass) { |
| ... | ... | @@ -573,16 +620,8 @@ static bool qual_type_has_wrapping_overflow(Context *c, QualType qt) { |
| 573 | 620 | } |
| 574 | 621 | } |
| 575 | 622 | |
| 576 | | enum TransLRValue { |
| 577 | | TransLValue, |
| 578 | | TransRValue, |
| 579 | | }; |
| 580 | | |
| 581 | | static AstNode *trans_stmt(Context *c, bool result_used, AstNode *block, Stmt *stmt, TransLRValue lrval); |
| 582 | | static AstNode *const skip_add_to_block_node = (AstNode *) 0x2; |
| 583 | | |
| 584 | | static AstNode *trans_expr(Context *c, bool result_used, AstNode *block, Expr *expr, TransLRValue lrval) { |
| 585 | | return trans_stmt(c, result_used, block, expr, lrval); |
| 623 | static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const Expr *expr, TransLRValue lrval) { |
| 624 | return trans_stmt(c, result_used, scope, expr, lrval); |
| 586 | 625 | } |
| 587 | 626 | |
| 588 | 627 | static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &source_loc) { |
| ... | ... | @@ -922,32 +961,33 @@ static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &s |
| 922 | 961 | return trans_type(c, qt.getTypePtr(), source_loc); |
| 923 | 962 | } |
| 924 | 963 | |
| 925 | | static AstNode *trans_compound_stmt(Context *c, AstNode *parent, CompoundStmt *stmt) { |
| 926 | | AstNode *child_block = trans_create_node(c, NodeTypeBlock); |
| 927 | | for (CompoundStmt::body_iterator it = stmt->body_begin(), end_it = stmt->body_end(); it != end_it; ++it) { |
| 928 | | AstNode *child_node = trans_stmt(c, false, child_block, *it, TransRValue); |
| 964 | static AstNode *trans_compound_stmt(Context *c, TransScope *parent_scope, const CompoundStmt *stmt) { |
| 965 | TransScopeBlock *child_scope_block = trans_scope_block_create(c, parent_scope); |
| 966 | for (CompoundStmt::const_body_iterator it = stmt->body_begin(), end_it = stmt->body_end(); it != end_it; ++it) { |
| 967 | AstNode *child_node = trans_stmt(c, ResultUsedNo, &child_scope_block->base, *it, TransRValue); |
| 929 | 968 | if (child_node == nullptr) |
| 930 | 969 | return nullptr; |
| 931 | 970 | if (child_node != skip_add_to_block_node) |
| 932 | | child_block->data.block.statements.append(child_node); |
| 971 | child_scope_block->node->data.block.statements.append(child_node); |
| 933 | 972 | } |
| 934 | | return child_block; |
| 973 | c->child_scope = &child_scope_block->base; |
| 974 | return child_scope_block->node; |
| 935 | 975 | } |
| 936 | 976 | |
| 937 | | static AstNode *trans_return_stmt(Context *c, AstNode *block, ReturnStmt *stmt) { |
| 938 | | Expr *value_expr = stmt->getRetValue(); |
| 977 | static AstNode *trans_return_stmt(Context *c, TransScope *scope, const ReturnStmt *stmt) { |
| 978 | const Expr *value_expr = stmt->getRetValue(); |
| 939 | 979 | if (value_expr == nullptr) { |
| 940 | 980 | return trans_create_node(c, NodeTypeReturnExpr); |
| 941 | 981 | } else { |
| 942 | 982 | AstNode *return_node = trans_create_node(c, NodeTypeReturnExpr); |
| 943 | | return_node->data.return_expr.expr = trans_expr(c, true, block, value_expr, TransRValue); |
| 983 | return_node->data.return_expr.expr = trans_expr(c, ResultUsedYes, scope, value_expr, TransRValue); |
| 944 | 984 | if (return_node->data.return_expr.expr == nullptr) |
| 945 | 985 | return nullptr; |
| 946 | 986 | return return_node; |
| 947 | 987 | } |
| 948 | 988 | } |
| 949 | 989 | |
| 950 | | static AstNode *trans_integer_literal(Context *c, IntegerLiteral *stmt) { |
| 990 | static AstNode *trans_integer_literal(Context *c, const IntegerLiteral *stmt) { |
| 951 | 991 | llvm::APSInt result; |
| 952 | 992 | if (!stmt->EvaluateAsInt(result, *c->ctx)) { |
| 953 | 993 | emit_warning(c, stmt->getLocStart(), "invalid integer literal"); |
| ... | ... | @@ -956,54 +996,56 @@ static AstNode *trans_integer_literal(Context *c, IntegerLiteral *stmt) { |
| 956 | 996 | return trans_create_node_apint(c, result); |
| 957 | 997 | } |
| 958 | 998 | |
| 959 | | static AstNode *trans_conditional_operator(Context *c, bool result_used, AstNode *block, ConditionalOperator *stmt) { |
| 999 | static AstNode *trans_conditional_operator(Context *c, ResultUsed result_used, TransScope *scope, |
| 1000 | const ConditionalOperator *stmt) |
| 1001 | { |
| 960 | 1002 | AstNode *node = trans_create_node(c, NodeTypeIfBoolExpr); |
| 961 | 1003 | |
| 962 | 1004 | Expr *cond_expr = stmt->getCond(); |
| 963 | 1005 | Expr *true_expr = stmt->getTrueExpr(); |
| 964 | 1006 | Expr *false_expr = stmt->getFalseExpr(); |
| 965 | 1007 | |
| 966 | | node->data.if_bool_expr.condition = trans_expr(c, true, block, cond_expr, TransRValue); |
| 1008 | node->data.if_bool_expr.condition = trans_expr(c, ResultUsedYes, scope, cond_expr, TransRValue); |
| 967 | 1009 | if (node->data.if_bool_expr.condition == nullptr) |
| 968 | 1010 | return nullptr; |
| 969 | 1011 | |
| 970 | | node->data.if_bool_expr.then_block = trans_expr(c, result_used, block, true_expr, TransRValue); |
| 1012 | node->data.if_bool_expr.then_block = trans_expr(c, result_used, scope, true_expr, TransRValue); |
| 971 | 1013 | if (node->data.if_bool_expr.then_block == nullptr) |
| 972 | 1014 | return nullptr; |
| 973 | 1015 | |
| 974 | | node->data.if_bool_expr.else_node = trans_expr(c, result_used, block, false_expr, TransRValue); |
| 1016 | node->data.if_bool_expr.else_node = trans_expr(c, result_used, scope, false_expr, TransRValue); |
| 975 | 1017 | if (node->data.if_bool_expr.else_node == nullptr) |
| 976 | 1018 | return nullptr; |
| 977 | 1019 | |
| 978 | 1020 | return maybe_suppress_result(c, result_used, node); |
| 979 | 1021 | } |
| 980 | 1022 | |
| 981 | | static AstNode *trans_create_bin_op(Context *c, AstNode *block, Expr *lhs, BinOpType bin_op, Expr *rhs) { |
| 1023 | static AstNode *trans_create_bin_op(Context *c, TransScope *scope, Expr *lhs, BinOpType bin_op, Expr *rhs) { |
| 982 | 1024 | AstNode *node = trans_create_node(c, NodeTypeBinOpExpr); |
| 983 | 1025 | node->data.bin_op_expr.bin_op = bin_op; |
| 984 | 1026 | |
| 985 | | node->data.bin_op_expr.op1 = trans_expr(c, true, block, lhs, TransRValue); |
| 1027 | node->data.bin_op_expr.op1 = trans_expr(c, ResultUsedYes, scope, lhs, TransRValue); |
| 986 | 1028 | if (node->data.bin_op_expr.op1 == nullptr) |
| 987 | 1029 | return nullptr; |
| 988 | 1030 | |
| 989 | | node->data.bin_op_expr.op2 = trans_expr(c, true, block, rhs, TransRValue); |
| 1031 | node->data.bin_op_expr.op2 = trans_expr(c, ResultUsedYes, scope, rhs, TransRValue); |
| 990 | 1032 | if (node->data.bin_op_expr.op2 == nullptr) |
| 991 | 1033 | return nullptr; |
| 992 | 1034 | |
| 993 | 1035 | return node; |
| 994 | 1036 | } |
| 995 | 1037 | |
| 996 | | static AstNode *trans_create_assign(Context *c, bool result_used, AstNode *block, Expr *lhs, Expr *rhs) { |
| 997 | | if (!result_used) { |
| 1038 | static AstNode *trans_create_assign(Context *c, ResultUsed result_used, TransScope *scope, Expr *lhs, Expr *rhs) { |
| 1039 | if (result_used == ResultUsedNo) { |
| 998 | 1040 | // common case |
| 999 | 1041 | AstNode *node = trans_create_node(c, NodeTypeBinOpExpr); |
| 1000 | 1042 | node->data.bin_op_expr.bin_op = BinOpTypeAssign; |
| 1001 | 1043 | |
| 1002 | | node->data.bin_op_expr.op1 = trans_expr(c, true, block, lhs, TransLValue); |
| 1044 | node->data.bin_op_expr.op1 = trans_expr(c, ResultUsedYes, scope, lhs, TransLValue); |
| 1003 | 1045 | if (node->data.bin_op_expr.op1 == nullptr) |
| 1004 | 1046 | return nullptr; |
| 1005 | 1047 | |
| 1006 | | node->data.bin_op_expr.op2 = trans_expr(c, true, block, rhs, TransRValue); |
| 1048 | node->data.bin_op_expr.op2 = trans_expr(c, ResultUsedYes, scope, rhs, TransRValue); |
| 1007 | 1049 | if (node->data.bin_op_expr.op2 == nullptr) |
| 1008 | 1050 | return nullptr; |
| 1009 | 1051 | |
| ... | ... | @@ -1017,47 +1059,49 @@ static AstNode *trans_create_assign(Context *c, bool result_used, AstNode *block |
| 1017 | 1059 | // zig: _tmp |
| 1018 | 1060 | // zig: } |
| 1019 | 1061 | |
| 1020 | | AstNode *child_block = trans_create_node(c, NodeTypeBlock); |
| 1062 | TransScopeBlock *child_scope = trans_scope_block_create(c, scope); |
| 1021 | 1063 | |
| 1022 | 1064 | // const _tmp = rhs; |
| 1023 | | AstNode *rhs_node = trans_expr(c, true, child_block, rhs, TransRValue); |
| 1065 | AstNode *rhs_node = trans_expr(c, ResultUsedYes, &child_scope->base, rhs, TransRValue); |
| 1024 | 1066 | if (rhs_node == nullptr) return nullptr; |
| 1025 | 1067 | // TODO: avoid name collisions with generated variable names |
| 1026 | 1068 | Buf* tmp_var_name = buf_create_from_str("_tmp"); |
| 1027 | 1069 | AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, rhs_node); |
| 1028 | | child_block->data.block.statements.append(tmp_var_decl); |
| 1070 | child_scope->node->data.block.statements.append(tmp_var_decl); |
| 1029 | 1071 | |
| 1030 | 1072 | // lhs = _tmp; |
| 1031 | | AstNode *lhs_node = trans_expr(c, true, child_block, lhs, TransLValue); |
| 1073 | AstNode *lhs_node = trans_expr(c, ResultUsedYes, &child_scope->base, lhs, TransLValue); |
| 1032 | 1074 | if (lhs_node == nullptr) return nullptr; |
| 1033 | | child_block->data.block.statements.append( |
| 1075 | child_scope->node->data.block.statements.append( |
| 1034 | 1076 | trans_create_node_bin_op(c, lhs_node, BinOpTypeAssign, |
| 1035 | 1077 | trans_create_node_symbol(c, tmp_var_name))); |
| 1036 | 1078 | |
| 1037 | 1079 | // _tmp |
| 1038 | | child_block->data.block.statements.append(trans_create_node_symbol(c, tmp_var_name)); |
| 1039 | | child_block->data.block.last_statement_is_result_expression = true; |
| 1080 | child_scope->node->data.block.statements.append(trans_create_node_symbol(c, tmp_var_name)); |
| 1081 | child_scope->node->data.block.last_statement_is_result_expression = true; |
| 1040 | 1082 | |
| 1041 | | return child_block; |
| 1083 | return child_scope->node; |
| 1042 | 1084 | } |
| 1043 | 1085 | } |
| 1044 | 1086 | |
| 1045 | | static AstNode *trans_create_shift_op(Context *c, AstNode *block, QualType result_type, Expr *lhs_expr, BinOpType bin_op, Expr *rhs_expr) { |
| 1087 | static AstNode *trans_create_shift_op(Context *c, TransScope *scope, QualType result_type, |
| 1088 | Expr *lhs_expr, BinOpType bin_op, Expr *rhs_expr) |
| 1089 | { |
| 1046 | 1090 | const SourceLocation &rhs_location = rhs_expr->getLocStart(); |
| 1047 | 1091 | AstNode *rhs_type = qual_type_to_log2_int_ref(c, result_type, rhs_location); |
| 1048 | 1092 | // lhs >> u5(rh) |
| 1049 | 1093 | |
| 1050 | | AstNode *lhs = trans_expr(c, true, block, lhs_expr, TransLValue); |
| 1094 | AstNode *lhs = trans_expr(c, ResultUsedYes, scope, lhs_expr, TransLValue); |
| 1051 | 1095 | if (lhs == nullptr) return nullptr; |
| 1052 | 1096 | |
| 1053 | | AstNode *rhs = trans_expr(c, true, block, rhs_expr, TransRValue); |
| 1097 | AstNode *rhs = trans_expr(c, ResultUsedYes, scope, rhs_expr, TransRValue); |
| 1054 | 1098 | if (rhs == nullptr) return nullptr; |
| 1055 | 1099 | AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs); |
| 1056 | 1100 | |
| 1057 | 1101 | return trans_create_node_bin_op(c, lhs, bin_op, coerced_rhs); |
| 1058 | 1102 | } |
| 1059 | 1103 | |
| 1060 | | static AstNode *trans_binary_operator(Context *c, bool result_used, AstNode *block, BinaryOperator *stmt) { |
| 1104 | static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransScope *scope, const BinaryOperator *stmt) { |
| 1061 | 1105 | switch (stmt->getOpcode()) { |
| 1062 | 1106 | case BO_PtrMemD: |
| 1063 | 1107 | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_PtrMemD"); |
| ... | ... | @@ -1066,20 +1110,20 @@ static AstNode *trans_binary_operator(Context *c, bool result_used, AstNode *blo |
| 1066 | 1110 | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_PtrMemI"); |
| 1067 | 1111 | return nullptr; |
| 1068 | 1112 | case BO_Mul: |
| 1069 | | return trans_create_bin_op(c, block, stmt->getLHS(), |
| 1113 | return trans_create_bin_op(c, scope, stmt->getLHS(), |
| 1070 | 1114 | qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeMultWrap : BinOpTypeMult, |
| 1071 | 1115 | stmt->getRHS()); |
| 1072 | 1116 | case BO_Div: |
| 1073 | 1117 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) { |
| 1074 | 1118 | // unsigned/float division uses the operator |
| 1075 | | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeDiv, stmt->getRHS()); |
| 1119 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeDiv, stmt->getRHS()); |
| 1076 | 1120 | } else { |
| 1077 | 1121 | // signed integer division uses @divTrunc |
| 1078 | 1122 | AstNode *fn_call = trans_create_node_builtin_fn_call_str(c, "divTrunc"); |
| 1079 | | AstNode *lhs = trans_expr(c, true, block, stmt->getLHS(), TransLValue); |
| 1123 | AstNode *lhs = trans_expr(c, ResultUsedYes, scope, stmt->getLHS(), TransLValue); |
| 1080 | 1124 | if (lhs == nullptr) return nullptr; |
| 1081 | 1125 | fn_call->data.fn_call_expr.params.append(lhs); |
| 1082 | | AstNode *rhs = trans_expr(c, true, block, stmt->getRHS(), TransLValue); |
| 1126 | AstNode *rhs = trans_expr(c, ResultUsedYes, scope, stmt->getRHS(), TransLValue); |
| 1083 | 1127 | if (rhs == nullptr) return nullptr; |
| 1084 | 1128 | fn_call->data.fn_call_expr.params.append(rhs); |
| 1085 | 1129 | return fn_call; |
| ... | ... | @@ -1087,66 +1131,70 @@ static AstNode *trans_binary_operator(Context *c, bool result_used, AstNode *blo |
| 1087 | 1131 | case BO_Rem: |
| 1088 | 1132 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) { |
| 1089 | 1133 | // unsigned/float division uses the operator |
| 1090 | | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeMod, stmt->getRHS()); |
| 1134 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeMod, stmt->getRHS()); |
| 1091 | 1135 | } else { |
| 1092 | 1136 | // signed integer division uses @rem |
| 1093 | 1137 | AstNode *fn_call = trans_create_node_builtin_fn_call_str(c, "rem"); |
| 1094 | | AstNode *lhs = trans_expr(c, true, block, stmt->getLHS(), TransLValue); |
| 1138 | AstNode *lhs = trans_expr(c, ResultUsedYes, scope, stmt->getLHS(), TransLValue); |
| 1095 | 1139 | if (lhs == nullptr) return nullptr; |
| 1096 | 1140 | fn_call->data.fn_call_expr.params.append(lhs); |
| 1097 | | AstNode *rhs = trans_expr(c, true, block, stmt->getRHS(), TransLValue); |
| 1141 | AstNode *rhs = trans_expr(c, ResultUsedYes, scope, stmt->getRHS(), TransLValue); |
| 1098 | 1142 | if (rhs == nullptr) return nullptr; |
| 1099 | 1143 | fn_call->data.fn_call_expr.params.append(rhs); |
| 1100 | 1144 | return fn_call; |
| 1101 | 1145 | } |
| 1102 | 1146 | case BO_Add: |
| 1103 | | return trans_create_bin_op(c, block, stmt->getLHS(), |
| 1147 | return trans_create_bin_op(c, scope, stmt->getLHS(), |
| 1104 | 1148 | qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeAddWrap : BinOpTypeAdd, |
| 1105 | 1149 | stmt->getRHS()); |
| 1106 | 1150 | case BO_Sub: |
| 1107 | | return trans_create_bin_op(c, block, stmt->getLHS(), |
| 1151 | return trans_create_bin_op(c, scope, stmt->getLHS(), |
| 1108 | 1152 | qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeSubWrap : BinOpTypeSub, |
| 1109 | 1153 | stmt->getRHS()); |
| 1110 | 1154 | case BO_Shl: |
| 1111 | | return trans_create_shift_op(c, block, stmt->getType(), stmt->getLHS(), BinOpTypeBitShiftLeft, stmt->getRHS()); |
| 1155 | return trans_create_shift_op(c, scope, stmt->getType(), stmt->getLHS(), BinOpTypeBitShiftLeft, stmt->getRHS()); |
| 1112 | 1156 | case BO_Shr: |
| 1113 | | return trans_create_shift_op(c, block, stmt->getType(), stmt->getLHS(), BinOpTypeBitShiftRight, stmt->getRHS()); |
| 1157 | return trans_create_shift_op(c, scope, stmt->getType(), stmt->getLHS(), BinOpTypeBitShiftRight, stmt->getRHS()); |
| 1114 | 1158 | case BO_LT: |
| 1115 | | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeCmpLessThan, stmt->getRHS()); |
| 1159 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpLessThan, stmt->getRHS()); |
| 1116 | 1160 | case BO_GT: |
| 1117 | | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeCmpGreaterThan, stmt->getRHS()); |
| 1161 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpGreaterThan, stmt->getRHS()); |
| 1118 | 1162 | case BO_LE: |
| 1119 | | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeCmpLessOrEq, stmt->getRHS()); |
| 1163 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpLessOrEq, stmt->getRHS()); |
| 1120 | 1164 | case BO_GE: |
| 1121 | | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeCmpGreaterOrEq, stmt->getRHS()); |
| 1165 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpGreaterOrEq, stmt->getRHS()); |
| 1122 | 1166 | case BO_EQ: |
| 1123 | | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeCmpEq, stmt->getRHS()); |
| 1167 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpEq, stmt->getRHS()); |
| 1124 | 1168 | case BO_NE: |
| 1125 | | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeCmpNotEq, stmt->getRHS()); |
| 1169 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpNotEq, stmt->getRHS()); |
| 1126 | 1170 | case BO_And: |
| 1127 | | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeBinAnd, stmt->getRHS()); |
| 1171 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinAnd, stmt->getRHS()); |
| 1128 | 1172 | case BO_Xor: |
| 1129 | | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeBinXor, stmt->getRHS()); |
| 1173 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinXor, stmt->getRHS()); |
| 1130 | 1174 | case BO_Or: |
| 1131 | | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeBinOr, stmt->getRHS()); |
| 1175 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinOr, stmt->getRHS()); |
| 1132 | 1176 | case BO_LAnd: |
| 1133 | | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeBoolAnd, stmt->getRHS()); |
| 1177 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolAnd, stmt->getRHS()); |
| 1134 | 1178 | case BO_LOr: |
| 1135 | 1179 | // TODO: int vs bool |
| 1136 | | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeBoolOr, stmt->getRHS()); |
| 1180 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolOr, stmt->getRHS()); |
| 1137 | 1181 | case BO_Assign: |
| 1138 | | return trans_create_assign(c, result_used, block, stmt->getLHS(), stmt->getRHS()); |
| 1182 | return trans_create_assign(c, result_used, scope, stmt->getLHS(), stmt->getRHS()); |
| 1139 | 1183 | case BO_Comma: |
| 1140 | 1184 | { |
| 1141 | | block = trans_create_node(c, NodeTypeBlock); |
| 1142 | | AstNode *lhs = trans_expr(c, false, block, stmt->getLHS(), TransRValue); |
| 1143 | | if (lhs == nullptr) return nullptr; |
| 1144 | | block->data.block.statements.append(maybe_suppress_result(c, false, lhs)); |
| 1145 | | AstNode *rhs = trans_expr(c, result_used, block, stmt->getRHS(), TransRValue); |
| 1146 | | if (rhs == nullptr) return nullptr; |
| 1147 | | block->data.block.statements.append(maybe_suppress_result(c, result_used, rhs)); |
| 1148 | | block->data.block.last_statement_is_result_expression = true; |
| 1149 | | return block; |
| 1185 | TransScopeBlock *scope_block = trans_scope_block_create(c, scope); |
| 1186 | AstNode *lhs = trans_expr(c, ResultUsedNo, &scope_block->base, stmt->getLHS(), TransRValue); |
| 1187 | if (lhs == nullptr) |
| 1188 | return nullptr; |
| 1189 | scope_block->node->data.block.statements.append(maybe_suppress_result(c, ResultUsedNo, lhs)); |
| 1190 | |
| 1191 | AstNode *rhs = trans_expr(c, result_used, &scope_block->base, stmt->getRHS(), TransRValue); |
| 1192 | if (rhs == nullptr) |
| 1193 | return nullptr; |
| 1194 | scope_block->node->data.block.statements.append(maybe_suppress_result(c, result_used, rhs)); |
| 1195 | |
| 1196 | scope_block->node->data.block.last_statement_is_result_expression = true; |
| 1197 | return scope_block->node; |
| 1150 | 1198 | } |
| 1151 | 1199 | case BO_MulAssign: |
| 1152 | 1200 | case BO_DivAssign: |
| ... | ... | @@ -1164,18 +1212,20 @@ static AstNode *trans_binary_operator(Context *c, bool result_used, AstNode *blo |
| 1164 | 1212 | zig_unreachable(); |
| 1165 | 1213 | } |
| 1166 | 1214 | |
| 1167 | | static AstNode *trans_create_compound_assign_shift(Context *c, bool result_used, AstNode *block, CompoundAssignOperator *stmt, BinOpType assign_op, BinOpType bin_op) { |
| 1215 | static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result_used, TransScope *scope, |
| 1216 | const CompoundAssignOperator *stmt, BinOpType assign_op, BinOpType bin_op) |
| 1217 | { |
| 1168 | 1218 | const SourceLocation &rhs_location = stmt->getRHS()->getLocStart(); |
| 1169 | 1219 | AstNode *rhs_type = qual_type_to_log2_int_ref(c, stmt->getComputationLHSType(), rhs_location); |
| 1170 | 1220 | |
| 1171 | 1221 | bool use_intermediate_casts = stmt->getComputationLHSType().getTypePtr() != stmt->getComputationResultType().getTypePtr(); |
| 1172 | | if (!use_intermediate_casts && !result_used) { |
| 1222 | if (!use_intermediate_casts && result_used == ResultUsedNo) { |
| 1173 | 1223 | // simple common case, where the C and Zig are identical: |
| 1174 | 1224 | // lhs >>= rhs |
| 1175 | | AstNode *lhs = trans_expr(c, true, block, stmt->getLHS(), TransLValue); |
| 1225 | AstNode *lhs = trans_expr(c, ResultUsedYes, scope, stmt->getLHS(), TransLValue); |
| 1176 | 1226 | if (lhs == nullptr) return nullptr; |
| 1177 | 1227 | |
| 1178 | | AstNode *rhs = trans_expr(c, true, block, stmt->getRHS(), TransRValue); |
| 1228 | AstNode *rhs = trans_expr(c, ResultUsedYes, scope, stmt->getRHS(), TransRValue); |
| 1179 | 1229 | if (rhs == nullptr) return nullptr; |
| 1180 | 1230 | AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs); |
| 1181 | 1231 | |
| ... | ... | @@ -1190,20 +1240,20 @@ static AstNode *trans_create_compound_assign_shift(Context *c, bool result_used, |
| 1190 | 1240 | // zig: } |
| 1191 | 1241 | // where u5 is the appropriate type |
| 1192 | 1242 | |
| 1193 | | AstNode *child_block = trans_create_node(c, NodeTypeBlock); |
| 1243 | TransScopeBlock *child_scope = trans_scope_block_create(c, scope); |
| 1194 | 1244 | |
| 1195 | 1245 | // const _ref = &lhs; |
| 1196 | | AstNode *lhs = trans_expr(c, true, child_block, stmt->getLHS(), TransLValue); |
| 1246 | AstNode *lhs = trans_expr(c, ResultUsedYes, &child_scope->base, stmt->getLHS(), TransLValue); |
| 1197 | 1247 | if (lhs == nullptr) return nullptr; |
| 1198 | 1248 | AstNode *addr_of_lhs = trans_create_node_addr_of(c, false, false, lhs); |
| 1199 | 1249 | // TODO: avoid name collisions with generated variable names |
| 1200 | 1250 | Buf* tmp_var_name = buf_create_from_str("_ref"); |
| 1201 | 1251 | AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, addr_of_lhs); |
| 1202 | | child_block->data.block.statements.append(tmp_var_decl); |
| 1252 | child_scope->node->data.block.statements.append(tmp_var_decl); |
| 1203 | 1253 | |
| 1204 | 1254 | // *_ref = result_type(operation_type(*_ref) >> u5(rhs)); |
| 1205 | 1255 | |
| 1206 | | AstNode *rhs = trans_expr(c, true, child_block, stmt->getRHS(), TransRValue); |
| 1256 | AstNode *rhs = trans_expr(c, ResultUsedYes, &child_scope->base, stmt->getRHS(), TransRValue); |
| 1207 | 1257 | if (rhs == nullptr) return nullptr; |
| 1208 | 1258 | AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs); |
| 1209 | 1259 | |
| ... | ... | @@ -1220,27 +1270,29 @@ static AstNode *trans_create_compound_assign_shift(Context *c, bool result_used, |
| 1220 | 1270 | trans_create_node_symbol(c, tmp_var_name))), |
| 1221 | 1271 | bin_op, |
| 1222 | 1272 | coerced_rhs))); |
| 1223 | | child_block->data.block.statements.append(assign_statement); |
| 1273 | child_scope->node->data.block.statements.append(assign_statement); |
| 1224 | 1274 | |
| 1225 | | if (result_used) { |
| 1275 | if (result_used == ResultUsedYes) { |
| 1226 | 1276 | // *_ref |
| 1227 | | child_block->data.block.statements.append( |
| 1277 | child_scope->node->data.block.statements.append( |
| 1228 | 1278 | trans_create_node_prefix_op(c, PrefixOpDereference, |
| 1229 | 1279 | trans_create_node_symbol(c, tmp_var_name))); |
| 1230 | | child_block->data.block.last_statement_is_result_expression = true; |
| 1280 | child_scope->node->data.block.last_statement_is_result_expression = true; |
| 1231 | 1281 | } |
| 1232 | 1282 | |
| 1233 | | return child_block; |
| 1283 | return child_scope->node; |
| 1234 | 1284 | } |
| 1235 | 1285 | } |
| 1236 | 1286 | |
| 1237 | | static AstNode *trans_create_compound_assign(Context *c, bool result_used, AstNode *block, CompoundAssignOperator *stmt, BinOpType assign_op, BinOpType bin_op) { |
| 1238 | | if (!result_used) { |
| 1287 | static AstNode *trans_create_compound_assign(Context *c, ResultUsed result_used, TransScope *scope, |
| 1288 | const CompoundAssignOperator *stmt, BinOpType assign_op, BinOpType bin_op) |
| 1289 | { |
| 1290 | if (result_used == ResultUsedNo) { |
| 1239 | 1291 | // simple common case, where the C and Zig are identical: |
| 1240 | 1292 | // lhs += rhs |
| 1241 | | AstNode *lhs = trans_expr(c, true, block, stmt->getLHS(), TransLValue); |
| 1293 | AstNode *lhs = trans_expr(c, ResultUsedYes, scope, stmt->getLHS(), TransLValue); |
| 1242 | 1294 | if (lhs == nullptr) return nullptr; |
| 1243 | | AstNode *rhs = trans_expr(c, true, block, stmt->getRHS(), TransRValue); |
| 1295 | AstNode *rhs = trans_expr(c, ResultUsedYes, scope, stmt->getRHS(), TransRValue); |
| 1244 | 1296 | if (rhs == nullptr) return nullptr; |
| 1245 | 1297 | return trans_create_node_bin_op(c, lhs, assign_op, rhs); |
| 1246 | 1298 | } else { |
| ... | ... | @@ -1252,20 +1304,20 @@ static AstNode *trans_create_compound_assign(Context *c, bool result_used, AstNo |
| 1252 | 1304 | // zig: *_ref |
| 1253 | 1305 | // zig: } |
| 1254 | 1306 | |
| 1255 | | AstNode *child_block = trans_create_node(c, NodeTypeBlock); |
| 1307 | TransScopeBlock *child_scope = trans_scope_block_create(c, scope); |
| 1256 | 1308 | |
| 1257 | 1309 | // const _ref = &lhs; |
| 1258 | | AstNode *lhs = trans_expr(c, true, child_block, stmt->getLHS(), TransLValue); |
| 1310 | AstNode *lhs = trans_expr(c, ResultUsedYes, &child_scope->base, stmt->getLHS(), TransLValue); |
| 1259 | 1311 | if (lhs == nullptr) return nullptr; |
| 1260 | 1312 | AstNode *addr_of_lhs = trans_create_node_addr_of(c, false, false, lhs); |
| 1261 | 1313 | // TODO: avoid name collisions with generated variable names |
| 1262 | 1314 | Buf* tmp_var_name = buf_create_from_str("_ref"); |
| 1263 | 1315 | AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, addr_of_lhs); |
| 1264 | | child_block->data.block.statements.append(tmp_var_decl); |
| 1316 | child_scope->node->data.block.statements.append(tmp_var_decl); |
| 1265 | 1317 | |
| 1266 | 1318 | // *_ref = *_ref + rhs; |
| 1267 | 1319 | |
| 1268 | | AstNode *rhs = trans_expr(c, true, child_block, stmt->getRHS(), TransRValue); |
| 1320 | AstNode *rhs = trans_expr(c, ResultUsedYes, &child_scope->base, stmt->getRHS(), TransRValue); |
| 1269 | 1321 | if (rhs == nullptr) return nullptr; |
| 1270 | 1322 | |
| 1271 | 1323 | AstNode *assign_statement = trans_create_node_bin_op(c, |
| ... | ... | @@ -1277,26 +1329,28 @@ static AstNode *trans_create_compound_assign(Context *c, bool result_used, AstNo |
| 1277 | 1329 | trans_create_node_symbol(c, tmp_var_name)), |
| 1278 | 1330 | bin_op, |
| 1279 | 1331 | rhs)); |
| 1280 | | child_block->data.block.statements.append(assign_statement); |
| 1332 | child_scope->node->data.block.statements.append(assign_statement); |
| 1281 | 1333 | |
| 1282 | 1334 | // *_ref |
| 1283 | | child_block->data.block.statements.append( |
| 1335 | child_scope->node->data.block.statements.append( |
| 1284 | 1336 | trans_create_node_prefix_op(c, PrefixOpDereference, |
| 1285 | 1337 | trans_create_node_symbol(c, tmp_var_name))); |
| 1286 | | child_block->data.block.last_statement_is_result_expression = true; |
| 1338 | child_scope->node->data.block.last_statement_is_result_expression = true; |
| 1287 | 1339 | |
| 1288 | | return child_block; |
| 1340 | return child_scope->node; |
| 1289 | 1341 | } |
| 1290 | 1342 | } |
| 1291 | 1343 | |
| 1292 | 1344 | |
| 1293 | | static AstNode *trans_compound_assign_operator(Context *c, bool result_used, AstNode *block, CompoundAssignOperator *stmt) { |
| 1345 | static AstNode *trans_compound_assign_operator(Context *c, ResultUsed result_used, TransScope *scope, |
| 1346 | const CompoundAssignOperator *stmt) |
| 1347 | { |
| 1294 | 1348 | switch (stmt->getOpcode()) { |
| 1295 | 1349 | case BO_MulAssign: |
| 1296 | 1350 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) |
| 1297 | | return trans_create_compound_assign(c, result_used, block, stmt, BinOpTypeAssignTimesWrap, BinOpTypeMultWrap); |
| 1351 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignTimesWrap, BinOpTypeMultWrap); |
| 1298 | 1352 | else |
| 1299 | | return trans_create_compound_assign(c, result_used, block, stmt, BinOpTypeAssignTimes, BinOpTypeMult); |
| 1353 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignTimes, BinOpTypeMult); |
| 1300 | 1354 | case BO_DivAssign: |
| 1301 | 1355 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_DivAssign"); |
| 1302 | 1356 | return nullptr; |
| ... | ... | @@ -1305,24 +1359,24 @@ static AstNode *trans_compound_assign_operator(Context *c, bool result_used, Ast |
| 1305 | 1359 | return nullptr; |
| 1306 | 1360 | case BO_AddAssign: |
| 1307 | 1361 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) |
| 1308 | | return trans_create_compound_assign(c, result_used, block, stmt, BinOpTypeAssignPlusWrap, BinOpTypeAddWrap); |
| 1362 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap, BinOpTypeAddWrap); |
| 1309 | 1363 | else |
| 1310 | | return trans_create_compound_assign(c, result_used, block, stmt, BinOpTypeAssignPlus, BinOpTypeAdd); |
| 1364 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignPlus, BinOpTypeAdd); |
| 1311 | 1365 | case BO_SubAssign: |
| 1312 | 1366 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) |
| 1313 | | return trans_create_compound_assign(c, result_used, block, stmt, BinOpTypeAssignMinusWrap, BinOpTypeSubWrap); |
| 1367 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap, BinOpTypeSubWrap); |
| 1314 | 1368 | else |
| 1315 | | return trans_create_compound_assign(c, result_used, block, stmt, BinOpTypeAssignMinus, BinOpTypeSub); |
| 1369 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignMinus, BinOpTypeSub); |
| 1316 | 1370 | case BO_ShlAssign: |
| 1317 | | return trans_create_compound_assign_shift(c, result_used, block, stmt, BinOpTypeAssignBitShiftLeft, BinOpTypeBitShiftLeft); |
| 1371 | return trans_create_compound_assign_shift(c, result_used, scope, stmt, BinOpTypeAssignBitShiftLeft, BinOpTypeBitShiftLeft); |
| 1318 | 1372 | case BO_ShrAssign: |
| 1319 | | return trans_create_compound_assign_shift(c, result_used, block, stmt, BinOpTypeAssignBitShiftRight, BinOpTypeBitShiftRight); |
| 1373 | return trans_create_compound_assign_shift(c, result_used, scope, stmt, BinOpTypeAssignBitShiftRight, BinOpTypeBitShiftRight); |
| 1320 | 1374 | case BO_AndAssign: |
| 1321 | | return trans_create_compound_assign(c, result_used, block, stmt, BinOpTypeAssignBitAnd, BinOpTypeBinAnd); |
| 1375 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignBitAnd, BinOpTypeBinAnd); |
| 1322 | 1376 | case BO_XorAssign: |
| 1323 | | return trans_create_compound_assign(c, result_used, block, stmt, BinOpTypeAssignBitXor, BinOpTypeBinXor); |
| 1377 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignBitXor, BinOpTypeBinXor); |
| 1324 | 1378 | case BO_OrAssign: |
| 1325 | | return trans_create_compound_assign(c, result_used, block, stmt, BinOpTypeAssignBitOr, BinOpTypeBinOr); |
| 1379 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignBitOr, BinOpTypeBinOr); |
| 1326 | 1380 | case BO_PtrMemD: |
| 1327 | 1381 | case BO_PtrMemI: |
| 1328 | 1382 | case BO_Assign: |
| ... | ... | @@ -1351,13 +1405,13 @@ static AstNode *trans_compound_assign_operator(Context *c, bool result_used, Ast |
| 1351 | 1405 | zig_unreachable(); |
| 1352 | 1406 | } |
| 1353 | 1407 | |
| 1354 | | static AstNode *trans_implicit_cast_expr(Context *c, AstNode *block, ImplicitCastExpr *stmt) { |
| 1408 | static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const ImplicitCastExpr *stmt) { |
| 1355 | 1409 | switch (stmt->getCastKind()) { |
| 1356 | 1410 | case CK_LValueToRValue: |
| 1357 | | return trans_expr(c, true, block, stmt->getSubExpr(), TransRValue); |
| 1411 | return trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue); |
| 1358 | 1412 | case CK_IntegralCast: |
| 1359 | 1413 | { |
| 1360 | | AstNode *target_node = trans_expr(c, true, block, stmt->getSubExpr(), TransRValue); |
| 1414 | AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue); |
| 1361 | 1415 | if (target_node == nullptr) |
| 1362 | 1416 | return nullptr; |
| 1363 | 1417 | return trans_c_cast(c, stmt->getExprLoc(), stmt->getType(), target_node); |
| ... | ... | @@ -1365,14 +1419,14 @@ static AstNode *trans_implicit_cast_expr(Context *c, AstNode *block, ImplicitCas |
| 1365 | 1419 | case CK_FunctionToPointerDecay: |
| 1366 | 1420 | case CK_ArrayToPointerDecay: |
| 1367 | 1421 | { |
| 1368 | | AstNode *target_node = trans_expr(c, true, block, stmt->getSubExpr(), TransRValue); |
| 1422 | AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue); |
| 1369 | 1423 | if (target_node == nullptr) |
| 1370 | 1424 | return nullptr; |
| 1371 | 1425 | return target_node; |
| 1372 | 1426 | } |
| 1373 | 1427 | case CK_BitCast: |
| 1374 | 1428 | { |
| 1375 | | AstNode *target_node = trans_expr(c, true, block, stmt->getSubExpr(), TransRValue); |
| 1429 | AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue); |
| 1376 | 1430 | if (target_node == nullptr) |
| 1377 | 1431 | return nullptr; |
| 1378 | 1432 | |
| ... | ... | @@ -1549,8 +1603,8 @@ static AstNode *trans_implicit_cast_expr(Context *c, AstNode *block, ImplicitCas |
| 1549 | 1603 | zig_unreachable(); |
| 1550 | 1604 | } |
| 1551 | 1605 | |
| 1552 | | static AstNode *trans_decl_ref_expr(Context *c, DeclRefExpr *stmt, TransLRValue lrval) { |
| 1553 | | ValueDecl *value_decl = stmt->getDecl(); |
| 1606 | static AstNode *trans_decl_ref_expr(Context *c, const DeclRefExpr *stmt, TransLRValue lrval) { |
| 1607 | const ValueDecl *value_decl = stmt->getDecl(); |
| 1554 | 1608 | Buf *symbol_name = buf_create_from_str(decl_name(value_decl)); |
| 1555 | 1609 | if (lrval == TransLValue) { |
| 1556 | 1610 | c->ptr_params.put(symbol_name, true); |
| ... | ... | @@ -1558,15 +1612,17 @@ static AstNode *trans_decl_ref_expr(Context *c, DeclRefExpr *stmt, TransLRValue |
| 1558 | 1612 | return trans_create_node_symbol(c, symbol_name); |
| 1559 | 1613 | } |
| 1560 | 1614 | |
| 1561 | | static AstNode *trans_create_post_crement(Context *c, bool result_used, AstNode *block, UnaryOperator *stmt, BinOpType assign_op) { |
| 1615 | static AstNode *trans_create_post_crement(Context *c, ResultUsed result_used, TransScope *scope, |
| 1616 | const UnaryOperator *stmt, BinOpType assign_op) |
| 1617 | { |
| 1562 | 1618 | Expr *op_expr = stmt->getSubExpr(); |
| 1563 | 1619 | |
| 1564 | | if (!result_used) { |
| 1620 | if (result_used == ResultUsedNo) { |
| 1565 | 1621 | // common case |
| 1566 | 1622 | // c: expr++ |
| 1567 | 1623 | // zig: expr += 1 |
| 1568 | 1624 | return trans_create_node_bin_op(c, |
| 1569 | | trans_expr(c, true, block, op_expr, TransLValue), |
| 1625 | trans_expr(c, ResultUsedYes, scope, op_expr, TransLValue), |
| 1570 | 1626 | assign_op, |
| 1571 | 1627 | trans_create_node_unsigned(c, 1)); |
| 1572 | 1628 | } |
| ... | ... | @@ -1578,23 +1634,23 @@ static AstNode *trans_create_post_crement(Context *c, bool result_used, AstNode |
| 1578 | 1634 | // zig: *_ref += 1; |
| 1579 | 1635 | // zig: _tmp |
| 1580 | 1636 | // zig: } |
| 1581 | | AstNode *child_block = trans_create_node(c, NodeTypeBlock); |
| 1637 | TransScopeBlock *child_scope = trans_scope_block_create(c, scope); |
| 1582 | 1638 | |
| 1583 | 1639 | // const _ref = &expr; |
| 1584 | | AstNode *expr = trans_expr(c, true, child_block, op_expr, TransLValue); |
| 1640 | AstNode *expr = trans_expr(c, ResultUsedYes, &child_scope->base, op_expr, TransLValue); |
| 1585 | 1641 | if (expr == nullptr) return nullptr; |
| 1586 | 1642 | AstNode *addr_of_expr = trans_create_node_addr_of(c, false, false, expr); |
| 1587 | 1643 | // TODO: avoid name collisions with generated variable names |
| 1588 | 1644 | Buf* ref_var_name = buf_create_from_str("_ref"); |
| 1589 | 1645 | AstNode *ref_var_decl = trans_create_node_var_decl_local(c, true, ref_var_name, nullptr, addr_of_expr); |
| 1590 | | child_block->data.block.statements.append(ref_var_decl); |
| 1646 | child_scope->node->data.block.statements.append(ref_var_decl); |
| 1591 | 1647 | |
| 1592 | 1648 | // const _tmp = *_ref; |
| 1593 | 1649 | Buf* tmp_var_name = buf_create_from_str("_tmp"); |
| 1594 | 1650 | AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, |
| 1595 | 1651 | trans_create_node_prefix_op(c, PrefixOpDereference, |
| 1596 | 1652 | trans_create_node_symbol(c, ref_var_name))); |
| 1597 | | child_block->data.block.statements.append(tmp_var_decl); |
| 1653 | child_scope->node->data.block.statements.append(tmp_var_decl); |
| 1598 | 1654 | |
| 1599 | 1655 | // *_ref += 1; |
| 1600 | 1656 | AstNode *assign_statement = trans_create_node_bin_op(c, |
| ... | ... | @@ -1602,24 +1658,26 @@ static AstNode *trans_create_post_crement(Context *c, bool result_used, AstNode |
| 1602 | 1658 | trans_create_node_symbol(c, ref_var_name)), |
| 1603 | 1659 | assign_op, |
| 1604 | 1660 | trans_create_node_unsigned(c, 1)); |
| 1605 | | child_block->data.block.statements.append(assign_statement); |
| 1661 | child_scope->node->data.block.statements.append(assign_statement); |
| 1606 | 1662 | |
| 1607 | 1663 | // _tmp |
| 1608 | | child_block->data.block.statements.append(trans_create_node_symbol(c, tmp_var_name)); |
| 1609 | | child_block->data.block.last_statement_is_result_expression = true; |
| 1664 | child_scope->node->data.block.statements.append(trans_create_node_symbol(c, tmp_var_name)); |
| 1665 | child_scope->node->data.block.last_statement_is_result_expression = true; |
| 1610 | 1666 | |
| 1611 | | return child_block; |
| 1667 | return child_scope->node; |
| 1612 | 1668 | } |
| 1613 | 1669 | |
| 1614 | | static AstNode *trans_create_pre_crement(Context *c, bool result_used, AstNode *block, UnaryOperator *stmt, BinOpType assign_op) { |
| 1670 | static AstNode *trans_create_pre_crement(Context *c, ResultUsed result_used, TransScope *scope, |
| 1671 | const UnaryOperator *stmt, BinOpType assign_op) |
| 1672 | { |
| 1615 | 1673 | Expr *op_expr = stmt->getSubExpr(); |
| 1616 | 1674 | |
| 1617 | | if (!result_used) { |
| 1675 | if (result_used == ResultUsedNo) { |
| 1618 | 1676 | // common case |
| 1619 | 1677 | // c: ++expr |
| 1620 | 1678 | // zig: expr += 1 |
| 1621 | 1679 | return trans_create_node_bin_op(c, |
| 1622 | | trans_expr(c, true, block, op_expr, TransLValue), |
| 1680 | trans_expr(c, ResultUsedYes, scope, op_expr, TransLValue), |
| 1623 | 1681 | assign_op, |
| 1624 | 1682 | trans_create_node_unsigned(c, 1)); |
| 1625 | 1683 | } |
| ... | ... | @@ -1630,16 +1688,16 @@ static AstNode *trans_create_pre_crement(Context *c, bool result_used, AstNode * |
| 1630 | 1688 | // zig: *_ref += 1; |
| 1631 | 1689 | // zig: *_ref |
| 1632 | 1690 | // zig: } |
| 1633 | | AstNode *child_block = trans_create_node(c, NodeTypeBlock); |
| 1691 | TransScopeBlock *child_scope = trans_scope_block_create(c, scope); |
| 1634 | 1692 | |
| 1635 | 1693 | // const _ref = &expr; |
| 1636 | | AstNode *expr = trans_expr(c, true, child_block, op_expr, TransLValue); |
| 1694 | AstNode *expr = trans_expr(c, ResultUsedYes, &child_scope->base, op_expr, TransLValue); |
| 1637 | 1695 | if (expr == nullptr) return nullptr; |
| 1638 | 1696 | AstNode *addr_of_expr = trans_create_node_addr_of(c, false, false, expr); |
| 1639 | 1697 | // TODO: avoid name collisions with generated variable names |
| 1640 | 1698 | Buf* ref_var_name = buf_create_from_str("_ref"); |
| 1641 | 1699 | AstNode *ref_var_decl = trans_create_node_var_decl_local(c, true, ref_var_name, nullptr, addr_of_expr); |
| 1642 | | child_block->data.block.statements.append(ref_var_decl); |
| 1700 | child_scope->node->data.block.statements.append(ref_var_decl); |
| 1643 | 1701 | |
| 1644 | 1702 | // *_ref += 1; |
| 1645 | 1703 | AstNode *assign_statement = trans_create_node_bin_op(c, |
| ... | ... | @@ -1647,49 +1705,49 @@ static AstNode *trans_create_pre_crement(Context *c, bool result_used, AstNode * |
| 1647 | 1705 | trans_create_node_symbol(c, ref_var_name)), |
| 1648 | 1706 | assign_op, |
| 1649 | 1707 | trans_create_node_unsigned(c, 1)); |
| 1650 | | child_block->data.block.statements.append(assign_statement); |
| 1708 | child_scope->node->data.block.statements.append(assign_statement); |
| 1651 | 1709 | |
| 1652 | 1710 | // *_ref |
| 1653 | 1711 | AstNode *deref_expr = trans_create_node_prefix_op(c, PrefixOpDereference, |
| 1654 | 1712 | trans_create_node_symbol(c, ref_var_name)); |
| 1655 | | child_block->data.block.statements.append(deref_expr); |
| 1656 | | child_block->data.block.last_statement_is_result_expression = true; |
| 1713 | child_scope->node->data.block.statements.append(deref_expr); |
| 1714 | child_scope->node->data.block.last_statement_is_result_expression = true; |
| 1657 | 1715 | |
| 1658 | | return child_block; |
| 1716 | return child_scope->node; |
| 1659 | 1717 | } |
| 1660 | 1718 | |
| 1661 | | static AstNode *trans_unary_operator(Context *c, bool result_used, AstNode *block, UnaryOperator *stmt) { |
| 1719 | static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransScope *scope, const UnaryOperator *stmt) { |
| 1662 | 1720 | switch (stmt->getOpcode()) { |
| 1663 | 1721 | case UO_PostInc: |
| 1664 | 1722 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) |
| 1665 | | return trans_create_post_crement(c, result_used, block, stmt, BinOpTypeAssignPlusWrap); |
| 1723 | return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap); |
| 1666 | 1724 | else |
| 1667 | | return trans_create_post_crement(c, result_used, block, stmt, BinOpTypeAssignPlus); |
| 1725 | return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignPlus); |
| 1668 | 1726 | case UO_PostDec: |
| 1669 | 1727 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) |
| 1670 | | return trans_create_post_crement(c, result_used, block, stmt, BinOpTypeAssignMinusWrap); |
| 1728 | return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap); |
| 1671 | 1729 | else |
| 1672 | | return trans_create_post_crement(c, result_used, block, stmt, BinOpTypeAssignMinus); |
| 1730 | return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignMinus); |
| 1673 | 1731 | case UO_PreInc: |
| 1674 | 1732 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) |
| 1675 | | return trans_create_pre_crement(c, result_used, block, stmt, BinOpTypeAssignPlusWrap); |
| 1733 | return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap); |
| 1676 | 1734 | else |
| 1677 | | return trans_create_pre_crement(c, result_used, block, stmt, BinOpTypeAssignPlus); |
| 1735 | return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignPlus); |
| 1678 | 1736 | case UO_PreDec: |
| 1679 | 1737 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) |
| 1680 | | return trans_create_pre_crement(c, result_used, block, stmt, BinOpTypeAssignMinusWrap); |
| 1738 | return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap); |
| 1681 | 1739 | else |
| 1682 | | return trans_create_pre_crement(c, result_used, block, stmt, BinOpTypeAssignMinus); |
| 1740 | return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignMinus); |
| 1683 | 1741 | case UO_AddrOf: |
| 1684 | 1742 | { |
| 1685 | | AstNode *value_node = trans_expr(c, result_used, block, stmt->getSubExpr(), TransLValue); |
| 1743 | AstNode *value_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), TransLValue); |
| 1686 | 1744 | if (value_node == nullptr) |
| 1687 | 1745 | return value_node; |
| 1688 | 1746 | return trans_create_node_addr_of(c, false, false, value_node); |
| 1689 | 1747 | } |
| 1690 | 1748 | case UO_Deref: |
| 1691 | 1749 | { |
| 1692 | | AstNode *value_node = trans_expr(c, result_used, block, stmt->getSubExpr(), TransRValue); |
| 1750 | AstNode *value_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), TransRValue); |
| 1693 | 1751 | if (value_node == nullptr) |
| 1694 | 1752 | return nullptr; |
| 1695 | 1753 | bool is_fn_ptr = qual_type_is_fn_ptr(c, stmt->getSubExpr()->getType()); |
| ... | ... | @@ -1708,7 +1766,7 @@ static AstNode *trans_unary_operator(Context *c, bool result_used, AstNode *bloc |
| 1708 | 1766 | AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr); |
| 1709 | 1767 | node->data.prefix_op_expr.prefix_op = PrefixOpNegation; |
| 1710 | 1768 | |
| 1711 | | node->data.prefix_op_expr.primary_expr = trans_expr(c, true, block, op_expr, TransRValue); |
| 1769 | node->data.prefix_op_expr.primary_expr = trans_expr(c, ResultUsedYes, scope, op_expr, TransRValue); |
| 1712 | 1770 | if (node->data.prefix_op_expr.primary_expr == nullptr) |
| 1713 | 1771 | return nullptr; |
| 1714 | 1772 | |
| ... | ... | @@ -1718,7 +1776,7 @@ static AstNode *trans_unary_operator(Context *c, bool result_used, AstNode *bloc |
| 1718 | 1776 | AstNode *node = trans_create_node(c, NodeTypeBinOpExpr); |
| 1719 | 1777 | node->data.bin_op_expr.op1 = trans_create_node_unsigned(c, 0); |
| 1720 | 1778 | |
| 1721 | | node->data.bin_op_expr.op2 = trans_expr(c, true, block, op_expr, TransRValue); |
| 1779 | node->data.bin_op_expr.op2 = trans_expr(c, ResultUsedYes, scope, op_expr, TransRValue); |
| 1722 | 1780 | if (node->data.bin_op_expr.op2 == nullptr) |
| 1723 | 1781 | return nullptr; |
| 1724 | 1782 | |
| ... | ... | @@ -1751,7 +1809,7 @@ static AstNode *trans_unary_operator(Context *c, bool result_used, AstNode *bloc |
| 1751 | 1809 | zig_unreachable(); |
| 1752 | 1810 | } |
| 1753 | 1811 | |
| 1754 | | static AstNode *trans_local_declaration(Context *c, AstNode *block, DeclStmt *stmt) { |
| 1812 | static AstNode *trans_local_declaration(Context *c, TransScope *scope, const DeclStmt *stmt) { |
| 1755 | 1813 | for (auto iter = stmt->decl_begin(); iter != stmt->decl_end(); iter++) { |
| 1756 | 1814 | Decl *decl = *iter; |
| 1757 | 1815 | switch (decl->getKind()) { |
| ... | ... | @@ -1760,7 +1818,7 @@ static AstNode *trans_local_declaration(Context *c, AstNode *block, DeclStmt *st |
| 1760 | 1818 | QualType qual_type = var_decl->getTypeSourceInfo()->getType(); |
| 1761 | 1819 | AstNode *init_node = nullptr; |
| 1762 | 1820 | if (var_decl->hasInit()) { |
| 1763 | | init_node = trans_expr(c, true, block, var_decl->getInit(), TransRValue); |
| 1821 | init_node = trans_expr(c, ResultUsedYes, scope, var_decl->getInit(), TransRValue); |
| 1764 | 1822 | if (init_node == nullptr) |
| 1765 | 1823 | return nullptr; |
| 1766 | 1824 | |
| ... | ... | @@ -1773,7 +1831,10 @@ static AstNode *trans_local_declaration(Context *c, AstNode *block, DeclStmt *st |
| 1773 | 1831 | |
| 1774 | 1832 | AstNode *node = trans_create_node_var_decl_local(c, qual_type.isConstQualified(), |
| 1775 | 1833 | symbol_name, type_node, init_node); |
| 1776 | | block->data.block.statements.append(node); |
| 1834 | |
| 1835 | assert(scope->id == TransScopeIdBlock); |
| 1836 | TransScopeBlock *scope_block = (TransScopeBlock *)scope; |
| 1837 | scope_block->node->data.block.statements.append(node); |
| 1777 | 1838 | continue; |
| 1778 | 1839 | } |
| 1779 | 1840 | case Decl::AccessSpec: |
| ... | ... | @@ -2000,37 +2061,37 @@ static AstNode *trans_local_declaration(Context *c, AstNode *block, DeclStmt *st |
| 2000 | 2061 | return skip_add_to_block_node; |
| 2001 | 2062 | } |
| 2002 | 2063 | |
| 2003 | | static AstNode *trans_while_loop(Context *c, AstNode *block, WhileStmt *stmt) { |
| 2064 | static AstNode *trans_while_loop(Context *c, TransScope *scope, const WhileStmt *stmt) { |
| 2004 | 2065 | AstNode *while_node = trans_create_node(c, NodeTypeWhileExpr); |
| 2005 | 2066 | |
| 2006 | | while_node->data.while_expr.condition = trans_expr(c, true, block, stmt->getCond(), TransRValue); |
| 2067 | while_node->data.while_expr.condition = trans_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue); |
| 2007 | 2068 | if (while_node->data.while_expr.condition == nullptr) |
| 2008 | 2069 | return nullptr; |
| 2009 | 2070 | |
| 2010 | | while_node->data.while_expr.body = trans_stmt(c, false, block, stmt->getBody(), TransRValue); |
| 2071 | while_node->data.while_expr.body = trans_stmt(c, ResultUsedNo, scope, stmt->getBody(), TransRValue); |
| 2011 | 2072 | if (while_node->data.while_expr.body == nullptr) |
| 2012 | 2073 | return nullptr; |
| 2013 | 2074 | |
| 2014 | 2075 | return while_node; |
| 2015 | 2076 | } |
| 2016 | 2077 | |
| 2017 | | static AstNode *trans_if_statement(Context *c, AstNode *block, IfStmt *stmt) { |
| 2078 | static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt *stmt) { |
| 2018 | 2079 | // if (c) t |
| 2019 | 2080 | // if (c) t else e |
| 2020 | 2081 | AstNode *if_node = trans_create_node(c, NodeTypeIfBoolExpr); |
| 2021 | 2082 | |
| 2022 | 2083 | // TODO: condition != 0 |
| 2023 | | AstNode *condition_node = trans_expr(c, true, block, stmt->getCond(), TransRValue); |
| 2084 | AstNode *condition_node = trans_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue); |
| 2024 | 2085 | if (condition_node == nullptr) |
| 2025 | 2086 | return nullptr; |
| 2026 | 2087 | if_node->data.if_bool_expr.condition = condition_node; |
| 2027 | 2088 | |
| 2028 | | if_node->data.if_bool_expr.then_block = trans_stmt(c, false, block, stmt->getThen(), TransRValue); |
| 2089 | if_node->data.if_bool_expr.then_block = trans_stmt(c, ResultUsedNo, scope, stmt->getThen(), TransRValue); |
| 2029 | 2090 | if (if_node->data.if_bool_expr.then_block == nullptr) |
| 2030 | 2091 | return nullptr; |
| 2031 | 2092 | |
| 2032 | 2093 | if (stmt->getElse() != nullptr) { |
| 2033 | | if_node->data.if_bool_expr.else_node = trans_stmt(c, false, block, stmt->getElse(), TransRValue); |
| 2094 | if_node->data.if_bool_expr.else_node = trans_stmt(c, ResultUsedNo, scope, stmt->getElse(), TransRValue); |
| 2034 | 2095 | if (if_node->data.if_bool_expr.else_node == nullptr) |
| 2035 | 2096 | return nullptr; |
| 2036 | 2097 | } |
| ... | ... | @@ -2038,10 +2099,10 @@ static AstNode *trans_if_statement(Context *c, AstNode *block, IfStmt *stmt) { |
| 2038 | 2099 | return if_node; |
| 2039 | 2100 | } |
| 2040 | 2101 | |
| 2041 | | static AstNode *trans_call_expr(Context *c, bool result_used, AstNode *block, CallExpr *stmt) { |
| 2102 | static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *scope, const CallExpr *stmt) { |
| 2042 | 2103 | AstNode *node = trans_create_node(c, NodeTypeFnCallExpr); |
| 2043 | 2104 | |
| 2044 | | AstNode *callee_raw_node = trans_expr(c, true, block, stmt->getCallee(), TransRValue); |
| 2105 | AstNode *callee_raw_node = trans_expr(c, ResultUsedYes, scope, stmt->getCallee(), TransRValue); |
| 2045 | 2106 | if (callee_raw_node == nullptr) |
| 2046 | 2107 | return nullptr; |
| 2047 | 2108 | |
| ... | ... | @@ -2055,9 +2116,9 @@ static AstNode *trans_call_expr(Context *c, bool result_used, AstNode *block, Ca |
| 2055 | 2116 | node->data.fn_call_expr.fn_ref_expr = callee_node; |
| 2056 | 2117 | |
| 2057 | 2118 | unsigned num_args = stmt->getNumArgs(); |
| 2058 | | Expr **args = stmt->getArgs(); |
| 2119 | const Expr * const* args = stmt->getArgs(); |
| 2059 | 2120 | for (unsigned i = 0; i < num_args; i += 1) { |
| 2060 | | AstNode *arg_node = trans_expr(c, true, block, args[i], TransRValue); |
| 2121 | AstNode *arg_node = trans_expr(c, ResultUsedYes, scope, args[i], TransRValue); |
| 2061 | 2122 | if (arg_node == nullptr) |
| 2062 | 2123 | return nullptr; |
| 2063 | 2124 | |
| ... | ... | @@ -2067,8 +2128,8 @@ static AstNode *trans_call_expr(Context *c, bool result_used, AstNode *block, Ca |
| 2067 | 2128 | return node; |
| 2068 | 2129 | } |
| 2069 | 2130 | |
| 2070 | | static AstNode *trans_member_expr(Context *c, AstNode *block, MemberExpr *stmt) { |
| 2071 | | AstNode *container_node = trans_expr(c, true, block, stmt->getBase(), TransRValue); |
| 2131 | static AstNode *trans_member_expr(Context *c, TransScope *scope, const MemberExpr *stmt) { |
| 2132 | AstNode *container_node = trans_expr(c, ResultUsedYes, scope, stmt->getBase(), TransRValue); |
| 2072 | 2133 | if (container_node == nullptr) |
| 2073 | 2134 | return nullptr; |
| 2074 | 2135 | |
| ... | ... | @@ -2082,12 +2143,12 @@ static AstNode *trans_member_expr(Context *c, AstNode *block, MemberExpr *stmt) |
| 2082 | 2143 | return node; |
| 2083 | 2144 | } |
| 2084 | 2145 | |
| 2085 | | static AstNode *trans_array_subscript_expr(Context *c, AstNode *block, ArraySubscriptExpr *stmt) { |
| 2086 | | AstNode *container_node = trans_expr(c, true, block, stmt->getBase(), TransRValue); |
| 2146 | static AstNode *trans_array_subscript_expr(Context *c, TransScope *scope, const ArraySubscriptExpr *stmt) { |
| 2147 | AstNode *container_node = trans_expr(c, ResultUsedYes, scope, stmt->getBase(), TransRValue); |
| 2087 | 2148 | if (container_node == nullptr) |
| 2088 | 2149 | return nullptr; |
| 2089 | 2150 | |
| 2090 | | AstNode *idx_node = trans_expr(c, true, block, stmt->getIdx(), TransRValue); |
| 2151 | AstNode *idx_node = trans_expr(c, ResultUsedYes, scope, stmt->getIdx(), TransRValue); |
| 2091 | 2152 | if (idx_node == nullptr) |
| 2092 | 2153 | return nullptr; |
| 2093 | 2154 | |
| ... | ... | @@ -2098,17 +2159,19 @@ static AstNode *trans_array_subscript_expr(Context *c, AstNode *block, ArraySubs |
| 2098 | 2159 | return node; |
| 2099 | 2160 | } |
| 2100 | 2161 | |
| 2101 | | static AstNode *trans_c_style_cast_expr(Context *c, bool result_used, AstNode *block, |
| 2102 | | CStyleCastExpr *stmt, TransLRValue lrvalue) |
| 2162 | static AstNode *trans_c_style_cast_expr(Context *c, ResultUsed result_used, TransScope *scope, |
| 2163 | const CStyleCastExpr *stmt, TransLRValue lrvalue) |
| 2103 | 2164 | { |
| 2104 | | AstNode *sub_expr_node = trans_expr(c, result_used, block, stmt->getSubExpr(), lrvalue); |
| 2165 | AstNode *sub_expr_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), lrvalue); |
| 2105 | 2166 | if (sub_expr_node == nullptr) |
| 2106 | 2167 | return nullptr; |
| 2107 | 2168 | |
| 2108 | 2169 | return trans_c_cast(c, stmt->getLocStart(), stmt->getType(), sub_expr_node); |
| 2109 | 2170 | } |
| 2110 | 2171 | |
| 2111 | | static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, AstNode *block, UnaryExprOrTypeTraitExpr *stmt) { |
| 2172 | static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, TransScope *scope, |
| 2173 | const UnaryExprOrTypeTraitExpr *stmt) |
| 2174 | { |
| 2112 | 2175 | AstNode *type_node = trans_qual_type(c, stmt->getTypeOfArgument(), stmt->getLocStart()); |
| 2113 | 2176 | if (type_node == nullptr) |
| 2114 | 2177 | return nullptr; |
| ... | ... | @@ -2118,7 +2181,7 @@ static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, AstNode *block, |
| 2118 | 2181 | return node; |
| 2119 | 2182 | } |
| 2120 | 2183 | |
| 2121 | | static AstNode *trans_do_loop(Context *c, AstNode *block, DoStmt *stmt) { |
| 2184 | static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const DoStmt *stmt) { |
| 2122 | 2185 | AstNode *while_node = trans_create_node(c, NodeTypeWhileExpr); |
| 2123 | 2186 | |
| 2124 | 2187 | AstNode *true_node = trans_create_node(c, NodeTypeBoolLiteral); |
| ... | ... | @@ -2126,6 +2189,7 @@ static AstNode *trans_do_loop(Context *c, AstNode *block, DoStmt *stmt) { |
| 2126 | 2189 | while_node->data.while_expr.condition = true_node; |
| 2127 | 2190 | |
| 2128 | 2191 | AstNode *body_node; |
| 2192 | TransScope *child_scope; |
| 2129 | 2193 | if (stmt->getBody()->getStmtClass() == Stmt::CompoundStmtClass) { |
| 2130 | 2194 | // there's already a block in C, so we'll append our condition to it. |
| 2131 | 2195 | // c: do { |
| ... | ... | @@ -2137,9 +2201,10 @@ static AstNode *trans_do_loop(Context *c, AstNode *block, DoStmt *stmt) { |
| 2137 | 2201 | // zig: b; |
| 2138 | 2202 | // zig: if (!cond) break; |
| 2139 | 2203 | // zig: } |
| 2140 | | body_node = trans_stmt(c, false, block, stmt->getBody(), TransRValue); |
| 2204 | body_node = trans_stmt(c, ResultUsedNo, parent_scope, stmt->getBody(), TransRValue); |
| 2141 | 2205 | if (body_node == nullptr) return nullptr; |
| 2142 | 2206 | assert(body_node->type == NodeTypeBlock); |
| 2207 | child_scope = c->child_scope; |
| 2143 | 2208 | } else { |
| 2144 | 2209 | // the C statement is without a block, so we need to create a block to contain it. |
| 2145 | 2210 | // c: do |
| ... | ... | @@ -2149,63 +2214,103 @@ static AstNode *trans_do_loop(Context *c, AstNode *block, DoStmt *stmt) { |
| 2149 | 2214 | // zig: a; |
| 2150 | 2215 | // zig: if (!cond) break; |
| 2151 | 2216 | // zig: } |
| 2152 | | body_node = trans_create_node(c, NodeTypeBlock); |
| 2153 | | AstNode *child_statement = trans_stmt(c, false, body_node, stmt->getBody(), TransRValue); |
| 2217 | TransScopeBlock *child_block_scope = trans_scope_block_create(c, parent_scope); |
| 2218 | body_node = child_block_scope->node; |
| 2219 | child_scope = &child_block_scope->base; |
| 2220 | AstNode *child_statement = trans_stmt(c, ResultUsedNo, child_scope, stmt->getBody(), TransRValue); |
| 2154 | 2221 | if (child_statement == nullptr) return nullptr; |
| 2155 | | body_node->data.block.statements.append(child_statement); |
| 2222 | child_block_scope->node->data.block.statements.append(child_statement); |
| 2156 | 2223 | } |
| 2157 | 2224 | |
| 2158 | 2225 | // if (!cond) break; |
| 2159 | | AstNode *condition_node = trans_expr(c, true, body_node, stmt->getCond(), TransRValue); |
| 2226 | AstNode *condition_node = trans_expr(c, ResultUsedYes, child_scope, stmt->getCond(), TransRValue); |
| 2160 | 2227 | if (condition_node == nullptr) return nullptr; |
| 2161 | 2228 | AstNode *terminator_node = trans_create_node(c, NodeTypeIfBoolExpr); |
| 2162 | 2229 | terminator_node->data.if_bool_expr.condition = trans_create_node_prefix_op(c, PrefixOpBoolNot, condition_node); |
| 2163 | 2230 | terminator_node->data.if_bool_expr.then_block = trans_create_node(c, NodeTypeBreak); |
| 2164 | | body_node->data.block.statements.append(terminator_node); |
| 2231 | |
| 2232 | assert(child_scope->id == TransScopeIdBlock); |
| 2233 | TransScopeBlock *child_block_scope = (TransScopeBlock *)child_scope; |
| 2234 | |
| 2235 | child_block_scope->node->data.block.statements.append(terminator_node); |
| 2165 | 2236 | |
| 2166 | 2237 | while_node->data.while_expr.body = body_node; |
| 2167 | 2238 | |
| 2168 | 2239 | return while_node; |
| 2169 | 2240 | } |
| 2170 | 2241 | |
| 2171 | | static AstNode *trans_for_loop(Context *c, AstNode *block, ForStmt *stmt) { |
| 2242 | //static AstNode *trans_switch_stmt(Context *c, TransScope *scope, const SwitchStmt *stmt) { |
| 2243 | // AstNode *switch_block_node = trans_create_node(c, NodeTypeBlock); |
| 2244 | // AstNode *switch_node = trans_create_node(c, NodeTypeSwitchExpr); |
| 2245 | // const DeclStmt *var_decl_stmt = stmt->getConditionVariableDeclStmt(); |
| 2246 | // if (var_decl_stmt != nullptr) { |
| 2247 | // AstNode *vars_node = trans_stmt(c, ResultUsedNo, switch_block_node, var_decl_stmt, TransRValue); |
| 2248 | // if (vars_node == nullptr) |
| 2249 | // return nullptr; |
| 2250 | // if (vars_node != skip_add_to_block_node) |
| 2251 | // switch_block_node->data.block.statements.append(vars_node); |
| 2252 | // } |
| 2253 | // switch_block_node->data.block.statements.append(switch_node); |
| 2254 | // |
| 2255 | // const Expr *cond_expr = stmt->getCond(); |
| 2256 | // assert(cond_expr != nullptr); |
| 2257 | // |
| 2258 | // AstNode *expr_node = trans_expr(c, ResultUsedYes, switch_block_node, cond_expr, TransRValue); |
| 2259 | // if (expr_node == nullptr) |
| 2260 | // return nullptr; |
| 2261 | // switch_node->data.switch_expr.expr = expr_node; |
| 2262 | // |
| 2263 | // AstNode *body_node = trans_stmt(c, ResultUsedNo, switch_block_node, stmt->getBody(), TransRValue); |
| 2264 | // if (body_node == nullptr) |
| 2265 | // return nullptr; |
| 2266 | // if (body_node != skip_add_to_block_node) |
| 2267 | // switch_block_node->data.block.statements.append(body_node); |
| 2268 | // |
| 2269 | // return switch_block_node; |
| 2270 | //} |
| 2271 | |
| 2272 | static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForStmt *stmt) { |
| 2172 | 2273 | AstNode *loop_block_node; |
| 2274 | TransScope *condition_scope; |
| 2173 | 2275 | AstNode *while_node = trans_create_node(c, NodeTypeWhileExpr); |
| 2174 | | Stmt *init_stmt = stmt->getInit(); |
| 2276 | const Stmt *init_stmt = stmt->getInit(); |
| 2175 | 2277 | if (init_stmt == nullptr) { |
| 2176 | 2278 | loop_block_node = while_node; |
| 2279 | condition_scope = parent_scope; |
| 2177 | 2280 | } else { |
| 2178 | | loop_block_node = trans_create_node(c, NodeTypeBlock); |
| 2281 | TransScopeBlock *child_scope = trans_scope_block_create(c, parent_scope); |
| 2282 | loop_block_node = child_scope->node; |
| 2283 | condition_scope = &child_scope->base; |
| 2179 | 2284 | |
| 2180 | | AstNode *vars_node = trans_stmt(c, false, loop_block_node, init_stmt, TransRValue); |
| 2285 | AstNode *vars_node = trans_stmt(c, ResultUsedNo, &child_scope->base, init_stmt, TransRValue); |
| 2181 | 2286 | if (vars_node == nullptr) |
| 2182 | 2287 | return nullptr; |
| 2183 | 2288 | if (vars_node != skip_add_to_block_node) |
| 2184 | | loop_block_node->data.block.statements.append(vars_node); |
| 2289 | child_scope->node->data.block.statements.append(vars_node); |
| 2185 | 2290 | |
| 2186 | | loop_block_node->data.block.statements.append(while_node); |
| 2291 | child_scope->node->data.block.statements.append(while_node); |
| 2187 | 2292 | } |
| 2188 | 2293 | |
| 2189 | | Stmt *cond_stmt = stmt->getCond(); |
| 2294 | const Stmt *cond_stmt = stmt->getCond(); |
| 2190 | 2295 | if (cond_stmt == nullptr) { |
| 2191 | 2296 | AstNode *true_node = trans_create_node(c, NodeTypeBoolLiteral); |
| 2192 | 2297 | true_node->data.bool_literal.value = true; |
| 2193 | 2298 | while_node->data.while_expr.condition = true_node; |
| 2194 | 2299 | } else { |
| 2195 | | while_node->data.while_expr.condition = trans_stmt(c, false, loop_block_node, cond_stmt, TransRValue); |
| 2300 | while_node->data.while_expr.condition = trans_stmt(c, ResultUsedNo, condition_scope, cond_stmt, TransRValue); |
| 2196 | 2301 | if (while_node->data.while_expr.condition == nullptr) |
| 2197 | 2302 | return nullptr; |
| 2198 | 2303 | } |
| 2199 | 2304 | |
| 2200 | | Stmt *inc_stmt = stmt->getInc(); |
| 2305 | const Stmt *inc_stmt = stmt->getInc(); |
| 2201 | 2306 | if (inc_stmt != nullptr) { |
| 2202 | | AstNode *inc_node = trans_stmt(c, false, loop_block_node, inc_stmt, TransRValue); |
| 2307 | AstNode *inc_node = trans_stmt(c, ResultUsedNo, condition_scope, inc_stmt, TransRValue); |
| 2203 | 2308 | if (inc_node == nullptr) |
| 2204 | 2309 | return nullptr; |
| 2205 | 2310 | while_node->data.while_expr.continue_expr = inc_node; |
| 2206 | 2311 | } |
| 2207 | 2312 | |
| 2208 | | AstNode *child_statement = trans_stmt(c, false, loop_block_node, stmt->getBody(), TransRValue); |
| 2313 | AstNode *child_statement = trans_stmt(c, ResultUsedNo, condition_scope, stmt->getBody(), TransRValue); |
| 2209 | 2314 | if (child_statement == nullptr) |
| 2210 | 2315 | return nullptr; |
| 2211 | 2316 | while_node->data.while_expr.body = child_statement; |
| ... | ... | @@ -2213,7 +2318,7 @@ static AstNode *trans_for_loop(Context *c, AstNode *block, ForStmt *stmt) { |
| 2213 | 2318 | return loop_block_node; |
| 2214 | 2319 | } |
| 2215 | 2320 | |
| 2216 | | static AstNode *trans_string_literal(Context *c, AstNode *block, StringLiteral *stmt) { |
| 2321 | static AstNode *trans_string_literal(Context *c, TransScope *scope, const StringLiteral *stmt) { |
| 2217 | 2322 | switch (stmt->getKind()) { |
| 2218 | 2323 | case StringLiteral::Ascii: |
| 2219 | 2324 | case StringLiteral::UTF8: |
| ... | ... | @@ -2231,72 +2336,75 @@ static AstNode *trans_string_literal(Context *c, AstNode *block, StringLiteral * |
| 2231 | 2336 | zig_unreachable(); |
| 2232 | 2337 | } |
| 2233 | 2338 | |
| 2234 | | static AstNode *trans_break_stmt(Context *c, AstNode *block, BreakStmt *stmt) { |
| 2339 | static AstNode *trans_break_stmt(Context *c, TransScope *scope, const BreakStmt *stmt) { |
| 2235 | 2340 | return trans_create_node(c, NodeTypeBreak); |
| 2236 | 2341 | } |
| 2237 | 2342 | |
| 2238 | | static AstNode *trans_continue_stmt(Context *c, AstNode *block, ContinueStmt *stmt) { |
| 2343 | static AstNode *trans_continue_stmt(Context *c, TransScope *scope, const ContinueStmt *stmt) { |
| 2239 | 2344 | return trans_create_node(c, NodeTypeContinue); |
| 2240 | 2345 | } |
| 2241 | 2346 | |
| 2242 | | static AstNode *trans_stmt(Context *c, bool result_used, AstNode *block, Stmt *stmt, TransLRValue lrvalue) { |
| 2347 | static AstNode *trans_stmt(Context *c, ResultUsed result_used, TransScope *scope, const Stmt *stmt, TransLRValue lrvalue) { |
| 2348 | c->child_scope = scope; // TODO refactor out |
| 2243 | 2349 | Stmt::StmtClass sc = stmt->getStmtClass(); |
| 2244 | 2350 | switch (sc) { |
| 2245 | 2351 | case Stmt::ReturnStmtClass: |
| 2246 | | return trans_return_stmt(c, block, (ReturnStmt *)stmt); |
| 2352 | return trans_return_stmt(c, scope, (const ReturnStmt *)stmt); |
| 2247 | 2353 | case Stmt::CompoundStmtClass: |
| 2248 | | return trans_compound_stmt(c, block, (CompoundStmt *)stmt); |
| 2354 | return trans_compound_stmt(c, scope, (const CompoundStmt *)stmt); |
| 2249 | 2355 | case Stmt::IntegerLiteralClass: |
| 2250 | | return trans_integer_literal(c, (IntegerLiteral *)stmt); |
| 2356 | return trans_integer_literal(c, (const IntegerLiteral *)stmt); |
| 2251 | 2357 | case Stmt::ConditionalOperatorClass: |
| 2252 | | return trans_conditional_operator(c, result_used, block, (ConditionalOperator *)stmt); |
| 2358 | return trans_conditional_operator(c, result_used, scope, (const ConditionalOperator *)stmt); |
| 2253 | 2359 | case Stmt::BinaryOperatorClass: |
| 2254 | | return trans_binary_operator(c, result_used, block, (BinaryOperator *)stmt); |
| 2360 | return trans_binary_operator(c, result_used, scope, (const BinaryOperator *)stmt); |
| 2255 | 2361 | case Stmt::CompoundAssignOperatorClass: |
| 2256 | | return trans_compound_assign_operator(c, result_used, block, (CompoundAssignOperator *)stmt); |
| 2362 | return trans_compound_assign_operator(c, result_used, scope, (const CompoundAssignOperator *)stmt); |
| 2257 | 2363 | case Stmt::ImplicitCastExprClass: |
| 2258 | | return trans_implicit_cast_expr(c, block, (ImplicitCastExpr *)stmt); |
| 2364 | return trans_implicit_cast_expr(c, scope, (const ImplicitCastExpr *)stmt); |
| 2259 | 2365 | case Stmt::DeclRefExprClass: |
| 2260 | | return trans_decl_ref_expr(c, (DeclRefExpr *)stmt, lrvalue); |
| 2366 | return trans_decl_ref_expr(c, (const DeclRefExpr *)stmt, lrvalue); |
| 2261 | 2367 | case Stmt::UnaryOperatorClass: |
| 2262 | | return trans_unary_operator(c, result_used, block, (UnaryOperator *)stmt); |
| 2368 | return trans_unary_operator(c, result_used, scope, (const UnaryOperator *)stmt); |
| 2263 | 2369 | case Stmt::DeclStmtClass: |
| 2264 | | return trans_local_declaration(c, block, (DeclStmt *)stmt); |
| 2370 | return trans_local_declaration(c, scope, (const DeclStmt *)stmt); |
| 2265 | 2371 | case Stmt::WhileStmtClass: |
| 2266 | | return trans_while_loop(c, block, (WhileStmt *)stmt); |
| 2372 | return trans_while_loop(c, scope, (const WhileStmt *)stmt); |
| 2267 | 2373 | case Stmt::IfStmtClass: |
| 2268 | | return trans_if_statement(c, block, (IfStmt *)stmt); |
| 2374 | return trans_if_statement(c, scope, (const IfStmt *)stmt); |
| 2269 | 2375 | case Stmt::CallExprClass: |
| 2270 | | return trans_call_expr(c, result_used, block, (CallExpr *)stmt); |
| 2376 | return trans_call_expr(c, result_used, scope, (const CallExpr *)stmt); |
| 2271 | 2377 | case Stmt::NullStmtClass: |
| 2272 | 2378 | return skip_add_to_block_node; |
| 2273 | 2379 | case Stmt::MemberExprClass: |
| 2274 | | return trans_member_expr(c, block, (MemberExpr *)stmt); |
| 2380 | return trans_member_expr(c, scope, (const MemberExpr *)stmt); |
| 2275 | 2381 | case Stmt::ArraySubscriptExprClass: |
| 2276 | | return trans_array_subscript_expr(c, block, (ArraySubscriptExpr *)stmt); |
| 2382 | return trans_array_subscript_expr(c, scope, (const ArraySubscriptExpr *)stmt); |
| 2277 | 2383 | case Stmt::CStyleCastExprClass: |
| 2278 | | return trans_c_style_cast_expr(c, result_used, block, (CStyleCastExpr *)stmt, lrvalue); |
| 2384 | return trans_c_style_cast_expr(c, result_used, scope, (const CStyleCastExpr *)stmt, lrvalue); |
| 2279 | 2385 | case Stmt::UnaryExprOrTypeTraitExprClass: |
| 2280 | | return trans_unary_expr_or_type_trait_expr(c, block, (UnaryExprOrTypeTraitExpr *)stmt); |
| 2386 | return trans_unary_expr_or_type_trait_expr(c, scope, (const UnaryExprOrTypeTraitExpr *)stmt); |
| 2281 | 2387 | case Stmt::DoStmtClass: |
| 2282 | | return trans_do_loop(c, block, (DoStmt *)stmt); |
| 2388 | return trans_do_loop(c, scope, (const DoStmt *)stmt); |
| 2283 | 2389 | case Stmt::ForStmtClass: |
| 2284 | | return trans_for_loop(c, block, (ForStmt *)stmt); |
| 2390 | return trans_for_loop(c, scope, (const ForStmt *)stmt); |
| 2285 | 2391 | case Stmt::StringLiteralClass: |
| 2286 | | return trans_string_literal(c, block, (StringLiteral *)stmt); |
| 2392 | return trans_string_literal(c, scope, (const StringLiteral *)stmt); |
| 2287 | 2393 | case Stmt::BreakStmtClass: |
| 2288 | | return trans_break_stmt(c, block, (BreakStmt *)stmt); |
| 2394 | return trans_break_stmt(c, scope, (const BreakStmt *)stmt); |
| 2289 | 2395 | case Stmt::ContinueStmtClass: |
| 2290 | | return trans_continue_stmt(c, block, (ContinueStmt *)stmt); |
| 2396 | return trans_continue_stmt(c, scope, (const ContinueStmt *)stmt); |
| 2397 | // case Stmt::SwitchStmtClass: |
| 2398 | // return trans_switch_stmt(c, scope, (const SwitchStmt *)stmt); |
| 2399 | case Stmt::SwitchStmtClass: |
| 2400 | emit_warning(c, stmt->getLocStart(), "TODO handle C SwitchStmtClass"); |
| 2401 | return nullptr; |
| 2291 | 2402 | case Stmt::CaseStmtClass: |
| 2292 | 2403 | emit_warning(c, stmt->getLocStart(), "TODO handle C CaseStmtClass"); |
| 2293 | 2404 | return nullptr; |
| 2294 | 2405 | case Stmt::DefaultStmtClass: |
| 2295 | 2406 | emit_warning(c, stmt->getLocStart(), "TODO handle C DefaultStmtClass"); |
| 2296 | 2407 | return nullptr; |
| 2297 | | case Stmt::SwitchStmtClass: |
| 2298 | | emit_warning(c, stmt->getLocStart(), "TODO handle C SwitchStmtClass"); |
| 2299 | | return nullptr; |
| 2300 | 2408 | case Stmt::NoStmtClass: |
| 2301 | 2409 | emit_warning(c, stmt->getLocStart(), "TODO handle C NoStmtClass"); |
| 2302 | 2410 | return nullptr; |
| ... | ... | @@ -2584,7 +2692,7 @@ static AstNode *trans_stmt(Context *c, bool result_used, AstNode *block, Stmt *s |
| 2584 | 2692 | emit_warning(c, stmt->getLocStart(), "TODO handle C PackExpansionExprClass"); |
| 2585 | 2693 | return nullptr; |
| 2586 | 2694 | case Stmt::ParenExprClass: |
| 2587 | | return trans_expr(c, result_used, block, ((ParenExpr*)stmt)->getSubExpr(), lrvalue); |
| 2695 | return trans_expr(c, result_used, scope, ((const ParenExpr*)stmt)->getSubExpr(), lrvalue); |
| 2588 | 2696 | case Stmt::ParenListExprClass: |
| 2589 | 2697 | emit_warning(c, stmt->getLocStart(), "TODO handle C ParenListExprClass"); |
| 2590 | 2698 | return nullptr; |
| ... | ... | @@ -2838,10 +2946,13 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { |
| 2838 | 2946 | return; |
| 2839 | 2947 | } |
| 2840 | 2948 | |
| 2949 | TransScope *scope = nullptr; |
| 2950 | |
| 2841 | 2951 | for (size_t i = 0; i < proto_node->data.fn_proto.params.length; i += 1) { |
| 2842 | 2952 | AstNode *param_node = proto_node->data.fn_proto.params.at(i); |
| 2843 | 2953 | const ParmVarDecl *param = fn_decl->getParamDecl(i); |
| 2844 | 2954 | const char *name = decl_name(param); |
| 2955 | |
| 2845 | 2956 | Buf *proto_param_name; |
| 2846 | 2957 | if (strlen(name) != 0) { |
| 2847 | 2958 | proto_param_name = buf_create_from_str(name); |
| ... | ... | @@ -2851,7 +2962,11 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { |
| 2851 | 2962 | proto_param_name = buf_sprintf("arg%" ZIG_PRI_usize "", i); |
| 2852 | 2963 | } |
| 2853 | 2964 | } |
| 2854 | | param_node->data.param_decl.name = proto_param_name; |
| 2965 | |
| 2966 | TransScopeVar *scope_var = trans_scope_var_create(c, scope, proto_param_name); |
| 2967 | scope = &scope_var->base; |
| 2968 | |
| 2969 | param_node->data.param_decl.name = scope_var->zig_name; |
| 2855 | 2970 | } |
| 2856 | 2971 | |
| 2857 | 2972 | if (!fn_decl->hasBody()) { |
| ... | ... | @@ -2863,7 +2978,7 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { |
| 2863 | 2978 | // actual function definition with body |
| 2864 | 2979 | c->ptr_params.clear(); |
| 2865 | 2980 | Stmt *body = fn_decl->getBody(); |
| 2866 | | AstNode *actual_body_node = trans_stmt(c, false, nullptr, body, TransRValue); |
| 2981 | AstNode *actual_body_node = trans_stmt(c, ResultUsedNo, scope, body, TransRValue); |
| 2867 | 2982 | assert(actual_body_node != skip_add_to_block_node); |
| 2868 | 2983 | if (actual_body_node == nullptr) { |
| 2869 | 2984 | emit_warning(c, fn_decl->getLocation(), "unable to translate function"); |
| ... | ... | @@ -3301,14 +3416,66 @@ static bool decl_visitor(void *context, const Decl *decl) { |
| 3301 | 3416 | return true; |
| 3302 | 3417 | } |
| 3303 | 3418 | |
| 3304 | | static bool name_exists(Context *c, Buf *name) { |
| 3419 | static bool name_exists_global(Context *c, Buf *name) { |
| 3305 | 3420 | return get_global(c, name) != nullptr; |
| 3306 | 3421 | } |
| 3307 | 3422 | |
| 3423 | static bool name_exists_scope(Context *c, Buf *name, TransScope *scope) { |
| 3424 | while (scope != nullptr) { |
| 3425 | if (scope->id == TransScopeIdVar) { |
| 3426 | TransScopeVar *var_scope = (TransScopeVar *)scope; |
| 3427 | if (buf_eql_buf(name, var_scope->zig_name)) { |
| 3428 | return true; |
| 3429 | } |
| 3430 | } |
| 3431 | scope = scope->parent; |
| 3432 | } |
| 3433 | return name_exists_global(c, name); |
| 3434 | } |
| 3435 | |
| 3436 | static Buf *get_unique_name(Context *c, Buf *name, TransScope *scope) { |
| 3437 | Buf *proposed_name = name; |
| 3438 | int count = 0; |
| 3439 | while (name_exists_scope(c, proposed_name, scope)) { |
| 3440 | if (proposed_name == name) { |
| 3441 | proposed_name = buf_alloc(); |
| 3442 | } |
| 3443 | buf_resize(proposed_name, 0); |
| 3444 | buf_appendf(proposed_name, "%s_%d", buf_ptr(name), count); |
| 3445 | count += 1; |
| 3446 | } |
| 3447 | return proposed_name; |
| 3448 | } |
| 3449 | |
| 3450 | static TransScopeBlock *trans_scope_block_create(Context *c, TransScope *parent_scope) { |
| 3451 | TransScopeBlock *result = allocate<TransScopeBlock>(1); |
| 3452 | result->base.id = TransScopeIdBlock; |
| 3453 | result->base.parent = parent_scope; |
| 3454 | result->node = trans_create_node(c, NodeTypeBlock); |
| 3455 | return result; |
| 3456 | } |
| 3457 | |
| 3458 | static TransScopeVar *trans_scope_var_create(Context *c, TransScope *parent_scope, Buf *wanted_name) { |
| 3459 | TransScopeVar *result = allocate<TransScopeVar>(1); |
| 3460 | result->base.id = TransScopeIdVar; |
| 3461 | result->base.parent = parent_scope; |
| 3462 | result->c_name = wanted_name; |
| 3463 | result->zig_name = get_unique_name(c, wanted_name, parent_scope); |
| 3464 | return result; |
| 3465 | } |
| 3466 | |
| 3467 | //static TransScopeSwitch *trans_scope_switch_create(Context *c, TransScope *parent_scope) { |
| 3468 | // TransScopeSwitch *result = allocate<TransScopeSwitch>(1); |
| 3469 | // result->base.id = TransScopeIdSwitch; |
| 3470 | // result->base.parent = parent_scope; |
| 3471 | // result->switch_node = trans_create_node(c, NodeTypeSwitchExpr); |
| 3472 | // return result; |
| 3473 | //} |
| 3474 | |
| 3308 | 3475 | static void render_aliases(Context *c) { |
| 3309 | 3476 | for (size_t i = 0; i < c->aliases.length; i += 1) { |
| 3310 | 3477 | Alias *alias = &c->aliases.at(i); |
| 3311 | | if (name_exists(c, alias->new_name)) |
| 3478 | if (name_exists_global(c, alias->new_name)) |
| 3312 | 3479 | continue; |
| 3313 | 3480 | |
| 3314 | 3481 | add_global_var(c, alias->new_name, trans_create_node_symbol(c, alias->canon_name)); |
| ... | ... | @@ -3438,7 +3605,7 @@ static void process_symbol_macros(Context *c) { |
| 3438 | 3605 | |
| 3439 | 3606 | // Check if this macro aliases another top level declaration |
| 3440 | 3607 | AstNode *existing_node = get_global(c, ms.value); |
| 3441 | | if (!existing_node || name_exists(c, ms.name)) |
| 3608 | if (!existing_node || name_exists_global(c, ms.name)) |
| 3442 | 3609 | continue; |
| 3443 | 3610 | |
| 3444 | 3611 | // If a macro aliases a global variable which is a function pointer, we conclude that |
| ... | ... | @@ -3487,7 +3654,7 @@ static void process_preprocessor_entities(Context *c, ASTUnit &unit) { |
| 3487 | 3654 | continue; |
| 3488 | 3655 | } |
| 3489 | 3656 | Buf *name = buf_create_from_str(raw_name); |
| 3490 | | if (name_exists(c, name)) { |
| 3657 | if (name_exists_global(c, name)) { |
| 3491 | 3658 | continue; |
| 3492 | 3659 | } |
| 3493 | 3660 | |