| ... | ... | @@ -49,6 +49,8 @@ struct Context { |
| 49 | 49 | |
| 50 | 50 | CodeGen *codegen; |
| 51 | 51 | ASTContext *ctx; |
| 52 | |
| 53 | HashMap<Buf *, bool, buf_hash, buf_eql_buf> ptr_params; |
| 52 | 54 | }; |
| 53 | 55 | |
| 54 | 56 | static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl); |
| ... | ... | @@ -441,11 +443,16 @@ static bool c_is_float(Context *c, QualType qt) { |
| 441 | 443 | } |
| 442 | 444 | } |
| 443 | 445 | |
| 444 | | static AstNode *trans_stmt(Context *c, bool result_used, AstNode *block, Stmt *stmt); |
| 446 | enum TransLRValue { |
| 447 | TransLValue, |
| 448 | TransRValue, |
| 449 | }; |
| 450 | |
| 451 | static AstNode *trans_stmt(Context *c, bool result_used, AstNode *block, Stmt *stmt, TransLRValue lrval); |
| 445 | 452 | static AstNode *const skip_add_to_block_node = (AstNode *) 0x2; |
| 446 | 453 | |
| 447 | | static AstNode *trans_expr(Context *c, bool result_used, AstNode *block, Expr *expr) { |
| 448 | | return trans_stmt(c, result_used, block, expr); |
| 454 | static AstNode *trans_expr(Context *c, bool result_used, AstNode *block, Expr *expr, TransLRValue lrval) { |
| 455 | return trans_stmt(c, result_used, block, expr, lrval); |
| 449 | 456 | } |
| 450 | 457 | |
| 451 | 458 | static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &source_loc) { |
| ... | ... | @@ -789,7 +796,7 @@ static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &s |
| 789 | 796 | static AstNode *trans_compound_stmt(Context *c, AstNode *parent, CompoundStmt *stmt) { |
| 790 | 797 | AstNode *child_block = trans_create_node(c, NodeTypeBlock); |
| 791 | 798 | for (CompoundStmt::body_iterator it = stmt->body_begin(), end_it = stmt->body_end(); it != end_it; ++it) { |
| 792 | | AstNode *child_node = trans_stmt(c, false, child_block, *it); |
| 799 | AstNode *child_node = trans_stmt(c, false, child_block, *it, TransRValue); |
| 793 | 800 | if (child_node == nullptr) |
| 794 | 801 | return nullptr; |
| 795 | 802 | if (child_node != skip_add_to_block_node) |
| ... | ... | @@ -805,7 +812,7 @@ static AstNode *trans_return_stmt(Context *c, AstNode *block, ReturnStmt *stmt) |
| 805 | 812 | return nullptr; |
| 806 | 813 | } else { |
| 807 | 814 | AstNode *return_node = trans_create_node(c, NodeTypeReturnExpr); |
| 808 | | return_node->data.return_expr.expr = trans_expr(c, true, block, value_expr); |
| 815 | return_node->data.return_expr.expr = trans_expr(c, true, block, value_expr, TransRValue); |
| 809 | 816 | if (return_node->data.return_expr.expr == nullptr) |
| 810 | 817 | return nullptr; |
| 811 | 818 | return return_node; |
| ... | ... | @@ -828,15 +835,15 @@ static AstNode *trans_conditional_operator(Context *c, bool result_used, AstNode |
| 828 | 835 | Expr *true_expr = stmt->getTrueExpr(); |
| 829 | 836 | Expr *false_expr = stmt->getFalseExpr(); |
| 830 | 837 | |
| 831 | | node->data.if_bool_expr.condition = trans_expr(c, true, block, cond_expr); |
| 838 | node->data.if_bool_expr.condition = trans_expr(c, true, block, cond_expr, TransRValue); |
| 832 | 839 | if (node->data.if_bool_expr.condition == nullptr) |
| 833 | 840 | return nullptr; |
| 834 | 841 | |
| 835 | | node->data.if_bool_expr.then_block = trans_expr(c, result_used, block, true_expr); |
| 842 | node->data.if_bool_expr.then_block = trans_expr(c, result_used, block, true_expr, TransRValue); |
| 836 | 843 | if (node->data.if_bool_expr.then_block == nullptr) |
| 837 | 844 | return nullptr; |
| 838 | 845 | |
| 839 | | node->data.if_bool_expr.else_node = trans_expr(c, result_used, block, false_expr); |
| 846 | node->data.if_bool_expr.else_node = trans_expr(c, result_used, block, false_expr, TransRValue); |
| 840 | 847 | if (node->data.if_bool_expr.else_node == nullptr) |
| 841 | 848 | return nullptr; |
| 842 | 849 | |
| ... | ... | @@ -847,11 +854,11 @@ static AstNode *trans_create_bin_op(Context *c, AstNode *block, Expr *lhs, BinOp |
| 847 | 854 | AstNode *node = trans_create_node(c, NodeTypeBinOpExpr); |
| 848 | 855 | node->data.bin_op_expr.bin_op = bin_op; |
| 849 | 856 | |
| 850 | | node->data.bin_op_expr.op1 = trans_expr(c, true, block, lhs); |
| 857 | node->data.bin_op_expr.op1 = trans_expr(c, true, block, lhs, TransRValue); |
| 851 | 858 | if (node->data.bin_op_expr.op1 == nullptr) |
| 852 | 859 | return nullptr; |
| 853 | 860 | |
| 854 | | node->data.bin_op_expr.op2 = trans_expr(c, true, block, rhs); |
| 861 | node->data.bin_op_expr.op2 = trans_expr(c, true, block, rhs, TransRValue); |
| 855 | 862 | if (node->data.bin_op_expr.op2 == nullptr) |
| 856 | 863 | return nullptr; |
| 857 | 864 | |
| ... | ... | @@ -992,7 +999,7 @@ static AstNode *trans_compound_assign_operator(Context *c, bool result_used, Ast |
| 992 | 999 | AstNode *child_block = trans_create_node(c, NodeTypeBlock); |
| 993 | 1000 | |
| 994 | 1001 | // const _ref = &lhs; |
| 995 | | AstNode *lhs = trans_expr(c, true, child_block, stmt->getLHS()); |
| 1002 | AstNode *lhs = trans_expr(c, true, child_block, stmt->getLHS(), TransLValue); |
| 996 | 1003 | if (lhs == nullptr) return nullptr; |
| 997 | 1004 | AstNode *addr_of_lhs = trans_create_node_addr_of(c, false, false, lhs); |
| 998 | 1005 | // TODO: avoid name collisions with generated variable names |
| ... | ... | @@ -1002,7 +1009,7 @@ static AstNode *trans_compound_assign_operator(Context *c, bool result_used, Ast |
| 1002 | 1009 | |
| 1003 | 1010 | // *_ref = result_type(operation_type(*_ref) >> u5(rhs)); |
| 1004 | 1011 | |
| 1005 | | AstNode *rhs = trans_expr(c, true, child_block, stmt->getRHS()); |
| 1012 | AstNode *rhs = trans_expr(c, true, child_block, stmt->getRHS(), TransRValue); |
| 1006 | 1013 | if (rhs == nullptr) return nullptr; |
| 1007 | 1014 | const SourceLocation &rhs_location = stmt->getRHS()->getLocStart(); |
| 1008 | 1015 | AstNode *rhs_type = qual_type_to_log2_int_ref(c, stmt->getComputationLHSType(), rhs_location); |
| ... | ... | @@ -1074,10 +1081,10 @@ static AstNode *trans_compound_assign_operator(Context *c, bool result_used, Ast |
| 1074 | 1081 | static AstNode *trans_implicit_cast_expr(Context *c, AstNode *block, ImplicitCastExpr *stmt) { |
| 1075 | 1082 | switch (stmt->getCastKind()) { |
| 1076 | 1083 | case CK_LValueToRValue: |
| 1077 | | return trans_expr(c, true, block, stmt->getSubExpr()); |
| 1084 | return trans_expr(c, true, block, stmt->getSubExpr(), TransRValue); |
| 1078 | 1085 | case CK_IntegralCast: |
| 1079 | 1086 | { |
| 1080 | | AstNode *target_node = trans_expr(c, true, block, stmt->getSubExpr()); |
| 1087 | AstNode *target_node = trans_expr(c, true, block, stmt->getSubExpr(), TransRValue); |
| 1081 | 1088 | if (target_node == nullptr) |
| 1082 | 1089 | return nullptr; |
| 1083 | 1090 | return trans_c_cast(c, stmt->getExprLoc(), stmt->getType(), target_node); |
| ... | ... | @@ -1254,10 +1261,13 @@ static AstNode *trans_implicit_cast_expr(Context *c, AstNode *block, ImplicitCas |
| 1254 | 1261 | zig_unreachable(); |
| 1255 | 1262 | } |
| 1256 | 1263 | |
| 1257 | | static AstNode *trans_decl_ref_expr(Context *c, DeclRefExpr *stmt) { |
| 1264 | static AstNode *trans_decl_ref_expr(Context *c, DeclRefExpr *stmt, TransLRValue lrval) { |
| 1258 | 1265 | ValueDecl *value_decl = stmt->getDecl(); |
| 1259 | | const char *name = decl_name(value_decl); |
| 1260 | | return trans_create_node_symbol_str(c, name); |
| 1266 | Buf *symbol_name = buf_create_from_str(decl_name(value_decl)); |
| 1267 | if (lrval == TransLValue) { |
| 1268 | c->ptr_params.put(symbol_name, true); |
| 1269 | } |
| 1270 | return trans_create_node_symbol(c, symbol_name); |
| 1261 | 1271 | } |
| 1262 | 1272 | |
| 1263 | 1273 | static AstNode *trans_unary_operator(Context *c, AstNode *block, UnaryOperator *stmt) { |
| ... | ... | @@ -1290,7 +1300,7 @@ static AstNode *trans_unary_operator(Context *c, AstNode *block, UnaryOperator * |
| 1290 | 1300 | AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr); |
| 1291 | 1301 | node->data.prefix_op_expr.prefix_op = PrefixOpNegation; |
| 1292 | 1302 | |
| 1293 | | node->data.prefix_op_expr.primary_expr = trans_expr(c, true, block, op_expr); |
| 1303 | node->data.prefix_op_expr.primary_expr = trans_expr(c, true, block, op_expr, TransRValue); |
| 1294 | 1304 | if (node->data.prefix_op_expr.primary_expr == nullptr) |
| 1295 | 1305 | return nullptr; |
| 1296 | 1306 | |
| ... | ... | @@ -1300,7 +1310,7 @@ static AstNode *trans_unary_operator(Context *c, AstNode *block, UnaryOperator * |
| 1300 | 1310 | AstNode *node = trans_create_node(c, NodeTypeBinOpExpr); |
| 1301 | 1311 | node->data.bin_op_expr.op1 = trans_create_node_unsigned(c, 0); |
| 1302 | 1312 | |
| 1303 | | node->data.bin_op_expr.op2 = trans_expr(c, true, block, op_expr); |
| 1313 | node->data.bin_op_expr.op2 = trans_expr(c, true, block, op_expr, TransRValue); |
| 1304 | 1314 | if (node->data.bin_op_expr.op2 == nullptr) |
| 1305 | 1315 | return nullptr; |
| 1306 | 1316 | |
| ... | ... | @@ -1342,7 +1352,7 @@ static AstNode *trans_local_declaration(Context *c, AstNode *block, DeclStmt *st |
| 1342 | 1352 | QualType qual_type = var_decl->getTypeSourceInfo()->getType(); |
| 1343 | 1353 | AstNode *init_node = nullptr; |
| 1344 | 1354 | if (var_decl->hasInit()) { |
| 1345 | | init_node = trans_expr(c, true, block, var_decl->getInit()); |
| 1355 | init_node = trans_expr(c, true, block, var_decl->getInit(), TransRValue); |
| 1346 | 1356 | if (init_node == nullptr) |
| 1347 | 1357 | return nullptr; |
| 1348 | 1358 | |
| ... | ... | @@ -1351,8 +1361,10 @@ static AstNode *trans_local_declaration(Context *c, AstNode *block, DeclStmt *st |
| 1351 | 1361 | if (type_node == nullptr) |
| 1352 | 1362 | return nullptr; |
| 1353 | 1363 | |
| 1364 | Buf *symbol_name = buf_create_from_str(decl_name(var_decl)); |
| 1365 | |
| 1354 | 1366 | AstNode *node = trans_create_node_var_decl_local(c, qual_type.isConstQualified(), |
| 1355 | | buf_create_from_str(decl_name(var_decl)), type_node, init_node); |
| 1367 | symbol_name, type_node, init_node); |
| 1356 | 1368 | block->data.block.statements.append(node); |
| 1357 | 1369 | continue; |
| 1358 | 1370 | } |
| ... | ... | @@ -1583,18 +1595,18 @@ static AstNode *trans_local_declaration(Context *c, AstNode *block, DeclStmt *st |
| 1583 | 1595 | static AstNode *trans_while_loop(Context *c, AstNode *block, WhileStmt *stmt) { |
| 1584 | 1596 | AstNode *while_node = trans_create_node(c, NodeTypeWhileExpr); |
| 1585 | 1597 | |
| 1586 | | while_node->data.while_expr.condition = trans_expr(c, true, block, stmt->getCond()); |
| 1598 | while_node->data.while_expr.condition = trans_expr(c, true, block, stmt->getCond(), TransRValue); |
| 1587 | 1599 | if (while_node->data.while_expr.condition == nullptr) |
| 1588 | 1600 | return nullptr; |
| 1589 | 1601 | |
| 1590 | | while_node->data.while_expr.body = trans_stmt(c, false, block, stmt->getBody()); |
| 1602 | while_node->data.while_expr.body = trans_stmt(c, false, block, stmt->getBody(), TransRValue); |
| 1591 | 1603 | if (while_node->data.while_expr.body == nullptr) |
| 1592 | 1604 | return nullptr; |
| 1593 | 1605 | |
| 1594 | 1606 | return while_node; |
| 1595 | 1607 | } |
| 1596 | 1608 | |
| 1597 | | static AstNode *trans_stmt(Context *c, bool result_used, AstNode *block, Stmt *stmt) { |
| 1609 | static AstNode *trans_stmt(Context *c, bool result_used, AstNode *block, Stmt *stmt, TransLRValue lrvalue) { |
| 1598 | 1610 | Stmt::StmtClass sc = stmt->getStmtClass(); |
| 1599 | 1611 | switch (sc) { |
| 1600 | 1612 | case Stmt::ReturnStmtClass: |
| ... | ... | @@ -1612,7 +1624,7 @@ static AstNode *trans_stmt(Context *c, bool result_used, AstNode *block, Stmt *s |
| 1612 | 1624 | case Stmt::ImplicitCastExprClass: |
| 1613 | 1625 | return trans_implicit_cast_expr(c, block, (ImplicitCastExpr *)stmt); |
| 1614 | 1626 | case Stmt::DeclRefExprClass: |
| 1615 | | return trans_decl_ref_expr(c, (DeclRefExpr *)stmt); |
| 1627 | return trans_decl_ref_expr(c, (DeclRefExpr *)stmt, lrvalue); |
| 1616 | 1628 | case Stmt::UnaryOperatorClass: |
| 1617 | 1629 | return trans_unary_operator(c, block, (UnaryOperator *)stmt); |
| 1618 | 1630 | case Stmt::DeclStmtClass: |
| ... | ... | @@ -2230,9 +2242,9 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { |
| 2230 | 2242 | } |
| 2231 | 2243 | |
| 2232 | 2244 | // actual function definition with body |
| 2233 | | |
| 2245 | c->ptr_params.clear(); |
| 2234 | 2246 | Stmt *body = fn_decl->getBody(); |
| 2235 | | AstNode *actual_body_node = trans_stmt(c, false, nullptr, body); |
| 2247 | AstNode *actual_body_node = trans_stmt(c, false, nullptr, body, TransRValue); |
| 2236 | 2248 | assert(actual_body_node != skip_add_to_block_node); |
| 2237 | 2249 | if (actual_body_node == nullptr) { |
| 2238 | 2250 | emit_warning(c, fn_decl->getLocation(), "unable to translate function"); |
| ... | ... | @@ -2247,14 +2259,17 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { |
| 2247 | 2259 | for (size_t i = 0; i < proto_node->data.fn_proto.params.length; i += 1) { |
| 2248 | 2260 | AstNode *param_node = proto_node->data.fn_proto.params.at(i); |
| 2249 | 2261 | Buf *good_name = param_node->data.param_decl.name; |
| 2250 | | // TODO: avoid name collisions |
| 2251 | | Buf *mangled_name = buf_sprintf("_arg_%s", buf_ptr(good_name)); |
| 2252 | | param_node->data.param_decl.name = mangled_name; |
| 2253 | 2262 | |
| 2254 | | // var c_name = _mangled_name; |
| 2255 | | AstNode *parameter_init = trans_create_node_var_decl_local(c, false, good_name, nullptr, trans_create_node_symbol(c, mangled_name)); |
| 2263 | if (c->ptr_params.maybe_get(good_name) != nullptr) { |
| 2264 | // TODO: avoid name collisions |
| 2265 | Buf *mangled_name = buf_sprintf("_arg_%s", buf_ptr(good_name)); |
| 2266 | param_node->data.param_decl.name = mangled_name; |
| 2256 | 2267 | |
| 2257 | | body_node_with_param_inits->data.block.statements.append(parameter_init); |
| 2268 | // var c_name = _mangled_name; |
| 2269 | AstNode *parameter_init = trans_create_node_var_decl_local(c, false, good_name, nullptr, trans_create_node_symbol(c, mangled_name)); |
| 2270 | |
| 2271 | body_node_with_param_inits->data.block.statements.append(parameter_init); |
| 2272 | } |
| 2258 | 2273 | } |
| 2259 | 2274 | |
| 2260 | 2275 | for (size_t i = 0; i < actual_body_node->data.block.statements.length; i += 1) { |
| ... | ... | @@ -2875,6 +2890,7 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const ch |
| 2875 | 2890 | c->visib_mod = VisibModPub; |
| 2876 | 2891 | c->decl_table.init(8); |
| 2877 | 2892 | c->macro_table.init(8); |
| 2893 | c->ptr_params.init(8); |
| 2878 | 2894 | c->codegen = codegen; |
| 2879 | 2895 | c->source_node = source_node; |
| 2880 | 2896 | |