| ... | ... | @@ -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); |
| ... | ... | @@ -126,13 +128,27 @@ static AstNode *trans_create_node_opaque(Context *c) { |
| 126 | 128 | return trans_create_node_builtin_fn_call_str(c, "OpaqueType"); |
| 127 | 129 | } |
| 128 | 130 | |
| 131 | static AstNode *trans_create_node_fn_call_1(Context *c, AstNode *fn_ref_expr, AstNode *arg1) { |
| 132 | AstNode *node = trans_create_node(c, NodeTypeFnCallExpr); |
| 133 | node->data.fn_call_expr.fn_ref_expr = fn_ref_expr; |
| 134 | node->data.fn_call_expr.params.append(arg1); |
| 135 | return node; |
| 136 | } |
| 137 | |
| 129 | 138 | static AstNode *trans_create_node_field_access(Context *c, AstNode *container, Buf *field_name) { |
| 130 | 139 | AstNode *node = trans_create_node(c, NodeTypeFieldAccessExpr); |
| 140 | 	if (container->type == NodeTypeSymbol) { |
| 141 | 		assert(container->data.symbol_expr.symbol != nullptr); |
| 142 | 	} |
| 131 | 143 | node->data.field_access_expr.struct_expr = container; |
| 132 | 144 | node->data.field_access_expr.field_name = field_name; |
| 133 | 145 | return node; |
| 134 | 146 | } |
| 135 | 147 | |
| 148 | static AstNode *trans_create_node_field_access_str(Context *c, AstNode *container, const char *field_name) { |
| 149 | return trans_create_node_field_access(c, container, buf_create_from_str(field_name)); |
| 150 | } |
| 151 | |
| 136 | 152 | static AstNode *trans_create_node_prefix_op(Context *c, PrefixOp op, AstNode *child_node) { |
| 137 | 153 | AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr); |
| 138 | 154 | node->data.prefix_op_expr.prefix_op = op; |
| ... | ... | @@ -140,6 +156,22 @@ static AstNode *trans_create_node_prefix_op(Context *c, PrefixOp op, AstNode *ch |
| 140 | 156 | return node; |
| 141 | 157 | } |
| 142 | 158 | |
| 159 | static AstNode *trans_create_node_bin_op(Context *c, AstNode *lhs_node, BinOpType op, AstNode *rhs_node) { |
| 160 | AstNode *node = trans_create_node(c, NodeTypeBinOpExpr); |
| 161 | node->data.bin_op_expr.op1 = lhs_node; |
| 162 | node->data.bin_op_expr.bin_op = op; |
| 163 | node->data.bin_op_expr.op2 = rhs_node; |
| 164 | return node; |
| 165 | } |
| 166 | |
| 167 | static AstNode *maybe_suppress_result(Context *c, bool result_used, AstNode *node) { |
| 168 | if (result_used) return node; |
| 169 | return trans_create_node_bin_op(c, |
| 170 | trans_create_node_symbol_str(c, "_"), |
| 171 | BinOpTypeAssign, |
| 172 | node); |
| 173 | } |
| 174 | |
| 143 | 175 | static AstNode *trans_create_node_addr_of(Context *c, bool is_const, bool is_volatile, AstNode *child_node) { |
| 144 | 176 | AstNode *node = trans_create_node(c, NodeTypeAddrOfExpr); |
| 145 | 177 | node->data.addr_of_expr.is_const = is_const; |
| ... | ... | @@ -155,6 +187,13 @@ static AstNode *trans_create_node_str_lit_c(Context *c, Buf *buf) { |
| 155 | 187 | return node; |
| 156 | 188 | } |
| 157 | 189 | |
| 190 | static AstNode *trans_create_node_str_lit_non_c(Context *c, Buf *buf) { |
| 191 | AstNode *node = trans_create_node(c, NodeTypeStringLiteral); |
| 192 | node->data.string_literal.buf = buf; |
| 193 | node->data.string_literal.c = false; |
| 194 | return node; |
| 195 | } |
| 196 | |
| 158 | 197 | static AstNode *trans_create_node_unsigned_negative(Context *c, uint64_t x, bool is_negative) { |
| 159 | 198 | AstNode *node = trans_create_node(c, NodeTypeIntLiteral); |
| 160 | 199 | node->data.int_literal.bigint = allocate<BigInt>(1); |
| ... | ... | @@ -188,11 +227,11 @@ static AstNode *trans_create_node_array_type(Context *c, AstNode *size_node, Ast |
| 188 | 227 | return node; |
| 189 | 228 | } |
| 190 | 229 | |
| 191 | | static AstNode *trans_create_node_var_decl(Context *c, bool is_const, Buf *var_name, AstNode *type_node, |
| 192 | | AstNode *init_node) |
| 230 | static AstNode *trans_create_node_var_decl(Context *c, VisibMod visib_mod, bool is_const, Buf *var_name, |
| 231 | AstNode *type_node, AstNode *init_node) |
| 193 | 232 | { |
| 194 | 233 | AstNode *node = trans_create_node(c, NodeTypeVariableDeclaration); |
| 195 | | node->data.variable_declaration.visib_mod = c->visib_mod; |
| 234 | node->data.variable_declaration.visib_mod = visib_mod; |
| 196 | 235 | node->data.variable_declaration.symbol = var_name; |
| 197 | 236 | node->data.variable_declaration.is_const = is_const; |
| 198 | 237 | node->data.variable_declaration.type = type_node; |
| ... | ... | @@ -200,6 +239,18 @@ static AstNode *trans_create_node_var_decl(Context *c, bool is_const, Buf *var_n |
| 200 | 239 | return node; |
| 201 | 240 | } |
| 202 | 241 | |
| 242 | static AstNode *trans_create_node_var_decl_global(Context *c, bool is_const, Buf *var_name, AstNode *type_node, |
| 243 | AstNode *init_node) |
| 244 | { |
| 245 | return trans_create_node_var_decl(c, c->visib_mod, is_const, var_name, type_node, init_node); |
| 246 | } |
| 247 | |
| 248 | static AstNode *trans_create_node_var_decl_local(Context *c, bool is_const, Buf *var_name, AstNode *type_node, |
| 249 | AstNode *init_node) |
| 250 | { |
| 251 | return trans_create_node_var_decl(c, VisibModPrivate, is_const, var_name, type_node, init_node); |
| 252 | } |
| 253 | |
| 203 | 254 | |
| 204 | 255 | static AstNode *trans_create_node_inline_fn(Context *c, Buf *fn_name, Buf *var_name, AstNode *src_proto_node) { |
| 205 | 256 | AstNode *fn_def = trans_create_node(c, NodeTypeFnDef); |
| ... | ... | @@ -240,6 +291,10 @@ static AstNode *trans_create_node_inline_fn(Context *c, Buf *fn_name, Buf *var_n |
| 240 | 291 | return fn_def; |
| 241 | 292 | } |
| 242 | 293 | |
| 294 | static AstNode *trans_create_node_unwrap_null(Context *c, AstNode *child) { |
| 295 | return trans_create_node_prefix_op(c, PrefixOpUnwrapMaybe, child); |
| 296 | } |
| 297 | |
| 243 | 298 | static AstNode *get_global(Context *c, Buf *name) { |
| 244 | 299 | for (size_t i = 0; i < c->root->data.root.top_level_decls.length; i += 1) { |
| 245 | 300 | AstNode *decl_node = c->root->data.root.top_level_decls.items[i]; |
| ... | ... | @@ -268,7 +323,7 @@ static AstNode *get_global(Context *c, Buf *name) { |
| 268 | 323 | static AstNode *add_global_var(Context *c, Buf *var_name, AstNode *value_node) { |
| 269 | 324 | bool is_const = true; |
| 270 | 325 | AstNode *type_node = nullptr; |
| 271 | | AstNode *node = trans_create_node_var_decl(c, is_const, var_name, type_node, value_node); |
| 326 | AstNode *node = trans_create_node_var_decl_global(c, is_const, var_name, type_node, value_node); |
| 272 | 327 | c->root->data.root.top_level_decls.append(node); |
| 273 | 328 | return node; |
| 274 | 329 | } |
| ... | ... | @@ -286,10 +341,96 @@ static AstNode *trans_create_node_apint(Context *c, const llvm::APSInt &aps_int) |
| 286 | 341 | |
| 287 | 342 | } |
| 288 | 343 | |
| 344 | static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc); |
| 345 | |
| 289 | 346 | static bool is_c_void_type(AstNode *node) { |
| 290 | 347 | return (node->type == NodeTypeSymbol && buf_eql_str(node->data.symbol_expr.symbol, "c_void")); |
| 291 | 348 | } |
| 292 | 349 | |
| 350 | static AstNode* trans_c_cast(Context *c, const SourceLocation &source_location, const QualType &qt, AstNode *expr) { |
| 351 | // TODO: maybe widen to increase size |
| 352 | // TODO: maybe bitcast to change sign |
| 353 | // TODO: maybe truncate to reduce size |
| 354 | return trans_create_node_fn_call_1(c, trans_qual_type(c, qt, source_location), expr); |
| 355 | } |
| 356 | |
| 357 | static uint32_t qual_type_int_bit_width(Context *c, const QualType &qt, const SourceLocation &source_loc) { |
| 358 | const Type *ty = qt.getTypePtr(); |
| 359 | switch (ty->getTypeClass()) { |
| 360 | case Type::Builtin: |
| 361 | { |
| 362 | const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(ty); |
| 363 | switch (builtin_ty->getKind()) { |
| 364 | case BuiltinType::Char_U: |
| 365 | case BuiltinType::UChar: |
| 366 | case BuiltinType::Char_S: |
| 367 | case BuiltinType::SChar: |
| 368 | return 8; |
| 369 | case BuiltinType::UInt128: |
| 370 | case BuiltinType::Int128: |
| 371 | return 128; |
| 372 | default: |
| 373 | return 0; |
| 374 | } |
| 375 | zig_unreachable(); |
| 376 | } |
| 377 | case Type::Typedef: |
| 378 | { |
| 379 | const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty); |
| 380 | const TypedefNameDecl *typedef_decl = typedef_ty->getDecl(); |
| 381 | const char *type_name = decl_name(typedef_decl); |
| 382 | if (strcmp(type_name, "uint8_t") == 0 || strcmp(type_name, "int8_t") == 0) { |
| 383 | return 8; |
| 384 | } else if (strcmp(type_name, "uint16_t") == 0 || strcmp(type_name, "int16_t") == 0) { |
| 385 | return 16; |
| 386 | } else if (strcmp(type_name, "uint32_t") == 0 || strcmp(type_name, "int32_t") == 0) { |
| 387 | return 32; |
| 388 | } else if (strcmp(type_name, "uint64_t") == 0 || strcmp(type_name, "int64_t") == 0) { |
| 389 | return 64; |
| 390 | } else { |
| 391 | return 0; |
| 392 | } |
| 393 | } |
| 394 | default: |
| 395 | return 0; |
| 396 | } |
| 397 | zig_unreachable(); |
| 398 | } |
| 399 | |
| 400 | |
| 401 | static AstNode *qual_type_to_log2_int_ref(Context *c, const QualType &qt, |
| 402 | const SourceLocation &source_loc) |
| 403 | { |
| 404 | uint32_t int_bit_width = qual_type_int_bit_width(c, qt, source_loc); |
| 405 | if (int_bit_width != 0) { |
| 406 | // we can perform the log2 now. |
| 407 | uint64_t cast_bit_width = log2_u64(int_bit_width); |
| 408 | return trans_create_node_symbol(c, buf_sprintf("u%" ZIG_PRI_u64, cast_bit_width)); |
| 409 | } |
| 410 | |
| 411 | AstNode *zig_type_node = trans_qual_type(c, qt, source_loc); |
| 412 | |
| 413 | // @import("std").math.Log2Int(c_long); |
| 414 | // |
| 415 | // FnCall |
| 416 | // FieldAccess |
| 417 | // FieldAccess |
| 418 | // FnCall (.builtin = true) |
| 419 | // Symbol "import" |
| 420 | // StringLiteral "std" |
| 421 | // Symbol "math" |
| 422 | // Symbol "Log2Int" |
| 423 | // zig_type_node |
| 424 | |
| 425 | AstNode *import_fn_call = trans_create_node_builtin_fn_call_str(c, "import"); |
| 426 | import_fn_call->data.fn_call_expr.params.append(trans_create_node_str_lit_non_c(c, buf_create_from_str("std"))); |
| 427 | AstNode *inner_field_access = trans_create_node_field_access_str(c, import_fn_call, "math"); |
| 428 | AstNode *outer_field_access = trans_create_node_field_access_str(c, inner_field_access, "Log2Int"); |
| 429 | AstNode *log2int_fn_call = trans_create_node_fn_call_1(c, outer_field_access, zig_type_node); |
| 430 | |
| 431 | return log2int_fn_call; |
| 432 | } |
| 433 | |
| 293 | 434 | static bool qual_type_child_is_fn_proto(const QualType &qt) { |
| 294 | 435 | if (qt.getTypePtr()->getTypeClass() == Type::Paren) { |
| 295 | 436 | const ParenType *paren_type = static_cast<const ParenType *>(qt.getTypePtr()); |
| ... | ... | @@ -303,8 +444,17 @@ static bool qual_type_child_is_fn_proto(const QualType &qt) { |
| 303 | 444 | return false; |
| 304 | 445 | } |
| 305 | 446 | |
| 447 | static QualType resolve_any_typedef(Context *c, QualType qt) { |
| 448 | const Type * ty = qt.getTypePtr(); |
| 449 | if (ty->getTypeClass() != Type::Typedef) |
| 450 | return qt; |
| 451 | const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty); |
| 452 | const TypedefNameDecl *typedef_decl = typedef_ty->getDecl(); |
| 453 | return typedef_decl->getUnderlyingType(); |
| 454 | } |
| 455 | |
| 306 | 456 | static bool c_is_signed_integer(Context *c, QualType qt) { |
| 307 | | const Type *c_type = qt.getTypePtr(); |
| 457 | const Type *c_type = resolve_any_typedef(c, qt).getTypePtr(); |
| 308 | 458 | if (c_type->getTypeClass() != Type::Builtin) |
| 309 | 459 | return false; |
| 310 | 460 | const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(c_type); |
| ... | ... | @@ -323,7 +473,7 @@ static bool c_is_signed_integer(Context *c, QualType qt) { |
| 323 | 473 | } |
| 324 | 474 | |
| 325 | 475 | static bool c_is_unsigned_integer(Context *c, QualType qt) { |
| 326 | | const Type *c_type = qt.getTypePtr(); |
| 476 | const Type *c_type = resolve_any_typedef(c, qt).getTypePtr(); |
| 327 | 477 | if (c_type->getTypeClass() != Type::Builtin) |
| 328 | 478 | return false; |
| 329 | 479 | const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(c_type); |
| ... | ... | @@ -360,12 +510,26 @@ static bool c_is_float(Context *c, QualType qt) { |
| 360 | 510 | } |
| 361 | 511 | } |
| 362 | 512 | |
| 363 | | static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt); |
| 364 | | static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc); |
| 513 | static bool qual_type_has_wrapping_overflow(Context *c, QualType qt) { |
| 514 | if (c_is_signed_integer(c, qt) || c_is_float(c, qt)) { |
| 515 | // float and signed integer overflow is undefined behavior. |
| 516 | return false; |
| 517 | } else { |
| 518 | // unsigned integer overflow wraps around. |
| 519 | return true; |
| 520 | } |
| 521 | } |
| 522 | |
| 523 | enum TransLRValue { |
| 524 | TransLValue, |
| 525 | TransRValue, |
| 526 | }; |
| 527 | |
| 528 | static AstNode *trans_stmt(Context *c, bool result_used, AstNode *block, Stmt *stmt, TransLRValue lrval); |
| 365 | 529 | static AstNode *const skip_add_to_block_node = (AstNode *) 0x2; |
| 366 | 530 | |
| 367 | | static AstNode *trans_expr(Context *c, AstNode *block, Expr *expr) { |
| 368 | | return trans_stmt(c, block, expr); |
| 531 | static AstNode *trans_expr(Context *c, bool result_used, AstNode *block, Expr *expr, TransLRValue lrval) { |
| 532 | return trans_stmt(c, result_used, block, expr, lrval); |
| 369 | 533 | } |
| 370 | 534 | |
| 371 | 535 | static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &source_loc) { |
| ... | ... | @@ -709,7 +873,7 @@ static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &s |
| 709 | 873 | static AstNode *trans_compound_stmt(Context *c, AstNode *parent, CompoundStmt *stmt) { |
| 710 | 874 | AstNode *child_block = trans_create_node(c, NodeTypeBlock); |
| 711 | 875 | for (CompoundStmt::body_iterator it = stmt->body_begin(), end_it = stmt->body_end(); it != end_it; ++it) { |
| 712 | | AstNode *child_node = trans_stmt(c, child_block, *it); |
| 876 | AstNode *child_node = trans_stmt(c, false, child_block, *it, TransRValue); |
| 713 | 877 | if (child_node == nullptr) |
| 714 | 878 | return nullptr; |
| 715 | 879 | if (child_node != skip_add_to_block_node) |
| ... | ... | @@ -725,7 +889,7 @@ static AstNode *trans_return_stmt(Context *c, AstNode *block, ReturnStmt *stmt) |
| 725 | 889 | return nullptr; |
| 726 | 890 | } else { |
| 727 | 891 | AstNode *return_node = trans_create_node(c, NodeTypeReturnExpr); |
| 728 | | return_node->data.return_expr.expr = trans_expr(c, block, value_expr); |
| 892 | return_node->data.return_expr.expr = trans_expr(c, true, block, value_expr, TransRValue); |
| 729 | 893 | if (return_node->data.return_expr.expr == nullptr) |
| 730 | 894 | return nullptr; |
| 731 | 895 | return return_node; |
| ... | ... | @@ -741,44 +905,93 @@ static AstNode *trans_integer_literal(Context *c, IntegerLiteral *stmt) { |
| 741 | 905 | return trans_create_node_apint(c, result); |
| 742 | 906 | } |
| 743 | 907 | |
| 744 | | static AstNode *trans_conditional_operator(Context *c, AstNode *block, ConditionalOperator *stmt) { |
| 908 | static AstNode *trans_conditional_operator(Context *c, bool result_used, AstNode *block, ConditionalOperator *stmt) { |
| 745 | 909 | AstNode *node = trans_create_node(c, NodeTypeIfBoolExpr); |
| 746 | 910 | |
| 747 | 911 | Expr *cond_expr = stmt->getCond(); |
| 748 | 912 | Expr *true_expr = stmt->getTrueExpr(); |
| 749 | 913 | Expr *false_expr = stmt->getFalseExpr(); |
| 750 | 914 | |
| 751 | | node->data.if_bool_expr.condition = trans_expr(c, block, cond_expr); |
| 915 | node->data.if_bool_expr.condition = trans_expr(c, true, block, cond_expr, TransRValue); |
| 752 | 916 | if (node->data.if_bool_expr.condition == nullptr) |
| 753 | 917 | return nullptr; |
| 754 | 918 | |
| 755 | | node->data.if_bool_expr.then_block = trans_expr(c, block, true_expr); |
| 919 | node->data.if_bool_expr.then_block = trans_expr(c, result_used, block, true_expr, TransRValue); |
| 756 | 920 | if (node->data.if_bool_expr.then_block == nullptr) |
| 757 | 921 | return nullptr; |
| 758 | 922 | |
| 759 | | node->data.if_bool_expr.else_node = trans_expr(c, block, false_expr); |
| 923 | node->data.if_bool_expr.else_node = trans_expr(c, result_used, block, false_expr, TransRValue); |
| 760 | 924 | if (node->data.if_bool_expr.else_node == nullptr) |
| 761 | 925 | return nullptr; |
| 762 | 926 | |
| 763 | | return node; |
| 927 | return maybe_suppress_result(c, result_used, node); |
| 764 | 928 | } |
| 765 | 929 | |
| 766 | 930 | static AstNode *trans_create_bin_op(Context *c, AstNode *block, Expr *lhs, BinOpType bin_op, Expr *rhs) { |
| 767 | 931 | AstNode *node = trans_create_node(c, NodeTypeBinOpExpr); |
| 768 | 932 | node->data.bin_op_expr.bin_op = bin_op; |
| 769 | 933 | |
| 770 | | node->data.bin_op_expr.op1 = trans_expr(c, block, lhs); |
| 934 | node->data.bin_op_expr.op1 = trans_expr(c, true, block, lhs, TransRValue); |
| 771 | 935 | if (node->data.bin_op_expr.op1 == nullptr) |
| 772 | 936 | return nullptr; |
| 773 | 937 | |
| 774 | | node->data.bin_op_expr.op2 = trans_expr(c, block, rhs); |
| 938 | node->data.bin_op_expr.op2 = trans_expr(c, true, block, rhs, TransRValue); |
| 775 | 939 | if (node->data.bin_op_expr.op2 == nullptr) |
| 776 | 940 | return nullptr; |
| 777 | 941 | |
| 778 | 942 | return node; |
| 779 | 943 | } |
| 780 | 944 | |
| 781 | | static AstNode *trans_binary_operator(Context *c, AstNode *block, BinaryOperator *stmt) { |
| 945 | static AstNode *trans_create_assign(Context *c, bool result_used, AstNode *block, Expr *lhs, Expr *rhs) { |
| 946 | if (!result_used) { |
| 947 | // common case |
| 948 | AstNode *node = trans_create_node(c, NodeTypeBinOpExpr); |
| 949 | node->data.bin_op_expr.bin_op = BinOpTypeAssign; |
| 950 | |
| 951 | node->data.bin_op_expr.op1 = trans_expr(c, true, block, lhs, TransLValue); |
| 952 | if (node->data.bin_op_expr.op1 == nullptr) |
| 953 | return nullptr; |
| 954 | |
| 955 | node->data.bin_op_expr.op2 = trans_expr(c, true, block, rhs, TransRValue); |
| 956 | if (node->data.bin_op_expr.op2 == nullptr) |
| 957 | return nullptr; |
| 958 | |
| 959 | return node; |
| 960 | } else { |
| 961 | // worst case |
| 962 | // c: lhs = rhs |
| 963 | // zig: { |
| 964 | // zig: const _tmp = rhs; |
| 965 | // zig: lhs = _tmp; |
| 966 | // zig: _tmp |
| 967 | // zig: } |
| 968 | |
| 969 | AstNode *child_block = trans_create_node(c, NodeTypeBlock); |
| 970 | |
| 971 | // const _tmp = rhs; |
| 972 | AstNode *rhs_node = trans_expr(c, true, child_block, rhs, TransRValue); |
| 973 | if (rhs_node == nullptr) return nullptr; |
| 974 | // TODO: avoid name collisions with generated variable names |
| 975 | Buf* tmp_var_name = buf_create_from_str("_tmp"); |
| 976 | AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, rhs_node); |
| 977 | child_block->data.block.statements.append(tmp_var_decl); |
| 978 | |
| 979 | // lhs = _tmp; |
| 980 | AstNode *lhs_node = trans_expr(c, true, child_block, lhs, TransLValue); |
| 981 | if (lhs_node == nullptr) return nullptr; |
| 982 | child_block->data.block.statements.append( |
| 983 | trans_create_node_bin_op(c, lhs_node, BinOpTypeAssign, |
| 984 | trans_create_node_symbol(c, tmp_var_name))); |
| 985 | |
| 986 | // _tmp |
| 987 | child_block->data.block.statements.append(trans_create_node_symbol(c, tmp_var_name)); |
| 988 | child_block->data.block.last_statement_is_result_expression = true; |
| 989 | |
| 990 | return child_block; |
| 991 | } |
| 992 | } |
| 993 | |
| 994 | static AstNode *trans_binary_operator(Context *c, bool result_used, AstNode *block, BinaryOperator *stmt) { |
| 782 | 995 | switch (stmt->getOpcode()) { |
| 783 | 996 | case BO_PtrMemD: |
| 784 | 997 | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_PtrMemD"); |
| ... | ... | @@ -787,20 +1000,47 @@ static AstNode *trans_binary_operator(Context *c, AstNode *block, BinaryOperator |
| 787 | 1000 | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_PtrMemI"); |
| 788 | 1001 | return nullptr; |
| 789 | 1002 | case BO_Mul: |
| 790 | | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_Mul"); |
| 791 | | return nullptr; |
| 1003 | return trans_create_bin_op(c, block, stmt->getLHS(), |
| 1004 | qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeMultWrap : BinOpTypeMult, |
| 1005 | stmt->getRHS()); |
| 792 | 1006 | case BO_Div: |
| 793 | | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_Div"); |
| 794 | | return nullptr; |
| 1007 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) { |
| 1008 | // unsigned/float division uses the operator |
| 1009 | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeDiv, stmt->getRHS()); |
| 1010 | } else { |
| 1011 | // signed integer division uses @divTrunc |
| 1012 | AstNode *fn_call = trans_create_node_builtin_fn_call_str(c, "divTrunc"); |
| 1013 | AstNode *lhs = trans_expr(c, true, block, stmt->getLHS(), TransLValue); |
| 1014 | if (lhs == nullptr) return nullptr; |
| 1015 | fn_call->data.fn_call_expr.params.append(lhs); |
| 1016 | AstNode *rhs = trans_expr(c, true, block, stmt->getRHS(), TransLValue); |
| 1017 | if (rhs == nullptr) return nullptr; |
| 1018 | fn_call->data.fn_call_expr.params.append(rhs); |
| 1019 | return fn_call; |
| 1020 | } |
| 795 | 1021 | case BO_Rem: |
| 796 | | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_Rem"); |
| 797 | | return nullptr; |
| 1022 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) { |
| 1023 | // unsigned/float division uses the operator |
| 1024 | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeMod, stmt->getRHS()); |
| 1025 | } else { |
| 1026 | // signed integer division uses @divTrunc |
| 1027 | AstNode *fn_call = trans_create_node_builtin_fn_call_str(c, "rem"); |
| 1028 | AstNode *lhs = trans_expr(c, true, block, stmt->getLHS(), TransLValue); |
| 1029 | if (lhs == nullptr) return nullptr; |
| 1030 | fn_call->data.fn_call_expr.params.append(lhs); |
| 1031 | AstNode *rhs = trans_expr(c, true, block, stmt->getRHS(), TransLValue); |
| 1032 | if (rhs == nullptr) return nullptr; |
| 1033 | fn_call->data.fn_call_expr.params.append(rhs); |
| 1034 | return fn_call; |
| 1035 | } |
| 798 | 1036 | case BO_Add: |
| 799 | | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_Add"); |
| 800 | | return nullptr; |
| 1037 | return trans_create_bin_op(c, block, stmt->getLHS(), |
| 1038 | qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeAddWrap : BinOpTypeAdd, |
| 1039 | stmt->getRHS()); |
| 801 | 1040 | case BO_Sub: |
| 802 | | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_Sub"); |
| 803 | | return nullptr; |
| 1041 | return trans_create_bin_op(c, block, stmt->getLHS(), |
| 1042 | qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeSubWrap : BinOpTypeSub, |
| 1043 | stmt->getRHS()); |
| 804 | 1044 | case BO_Shl: |
| 805 | 1045 | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_Shl"); |
| 806 | 1046 | return nullptr; |
| ... | ... | @@ -816,29 +1056,22 @@ static AstNode *trans_binary_operator(Context *c, AstNode *block, BinaryOperator |
| 816 | 1056 | case BO_GE: |
| 817 | 1057 | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeCmpGreaterOrEq, stmt->getRHS()); |
| 818 | 1058 | case BO_EQ: |
| 819 | | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_EQ"); |
| 820 | | return nullptr; |
| 1059 | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeCmpEq, stmt->getRHS()); |
| 821 | 1060 | case BO_NE: |
| 822 | | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_NE"); |
| 823 | | return nullptr; |
| 1061 | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeCmpNotEq, stmt->getRHS()); |
| 824 | 1062 | case BO_And: |
| 825 | | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_And"); |
| 826 | | return nullptr; |
| 1063 | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeBinAnd, stmt->getRHS()); |
| 827 | 1064 | case BO_Xor: |
| 828 | | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_Xor"); |
| 829 | | return nullptr; |
| 1065 | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeBinXor, stmt->getRHS()); |
| 830 | 1066 | case BO_Or: |
| 831 | | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_Or"); |
| 832 | | return nullptr; |
| 1067 | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeBinOr, stmt->getRHS()); |
| 833 | 1068 | case BO_LAnd: |
| 834 | | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_LAnd"); |
| 835 | | return nullptr; |
| 1069 | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeBoolAnd, stmt->getRHS()); |
| 836 | 1070 | case BO_LOr: |
| 837 | | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_LOr"); |
| 838 | | return nullptr; |
| 1071 | // TODO: int vs bool |
| 1072 | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeBoolOr, stmt->getRHS()); |
| 839 | 1073 | case BO_Assign: |
| 840 | | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_Assign"); |
| 841 | | return nullptr; |
| 1074 | return trans_create_assign(c, result_used, block, stmt->getLHS(), stmt->getRHS()); |
| 842 | 1075 | case BO_MulAssign: |
| 843 | 1076 | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_MulAssign"); |
| 844 | 1077 | return nullptr; |
| ... | ... | @@ -877,32 +1110,170 @@ static AstNode *trans_binary_operator(Context *c, AstNode *block, BinaryOperator |
| 877 | 1110 | zig_unreachable(); |
| 878 | 1111 | } |
| 879 | 1112 | |
| 1113 | static AstNode *trans_compound_assign_operator(Context *c, bool result_used, AstNode *block, CompoundAssignOperator *stmt) { |
| 1114 | switch (stmt->getOpcode()) { |
| 1115 | case BO_MulAssign: |
| 1116 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_MulAssign"); |
| 1117 | return nullptr; |
| 1118 | case BO_DivAssign: |
| 1119 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_DivAssign"); |
| 1120 | return nullptr; |
| 1121 | case BO_RemAssign: |
| 1122 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_RemAssign"); |
| 1123 | return nullptr; |
| 1124 | case BO_AddAssign: |
| 1125 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_AddAssign"); |
| 1126 | return nullptr; |
| 1127 | case BO_SubAssign: |
| 1128 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_SubAssign"); |
| 1129 | return nullptr; |
| 1130 | case BO_ShlAssign: |
| 1131 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_ShlAssign"); |
| 1132 | return nullptr; |
| 1133 | case BO_ShrAssign: { |
| 1134 | BinOpType bin_op = BinOpTypeBitShiftRight; |
| 1135 | |
| 1136 | const SourceLocation &rhs_location = stmt->getRHS()->getLocStart(); |
| 1137 | AstNode *rhs_type = qual_type_to_log2_int_ref(c, stmt->getComputationLHSType(), rhs_location); |
| 1138 | |
| 1139 | bool use_intermediate_casts = stmt->getComputationLHSType().getTypePtr() != stmt->getComputationResultType().getTypePtr(); |
| 1140 | if (!use_intermediate_casts && !result_used) { |
| 1141 | // simple common case, where the C and Zig are identical: |
| 1142 | // lhs >>= rh* s |
| 1143 | AstNode *lhs = trans_expr(c, true, block, stmt->getLHS(), TransLValue); |
| 1144 | if (lhs == nullptr) return nullptr; |
| 1145 | |
| 1146 | AstNode *rhs = trans_expr(c, true, block, stmt->getRHS(), TransRValue); |
| 1147 | if (rhs == nullptr) return nullptr; |
| 1148 | AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs); |
| 1149 | |
| 1150 | return trans_create_node_bin_op(c, lhs, BinOpTypeAssignBitShiftRight, coerced_rhs); |
| 1151 | } else { |
| 1152 | // need more complexity. worst case, this looks like this: |
| 1153 | // c: lhs >>= rhs |
| 1154 | // zig: { |
| 1155 | // zig: const _ref = &lhs; |
| 1156 | // zig: *_ref = result_type(operation_type(*_ref) >> u5(rhs)); |
| 1157 | // zig: *_ref |
| 1158 | // zig: } |
| 1159 | // where u5 is the appropriate type |
| 1160 | |
| 1161 | // TODO: avoid mess when we don't need the assignment value for chained assignments or anything. |
| 1162 | AstNode *child_block = trans_create_node(c, NodeTypeBlock); |
| 1163 | |
| 1164 | // const _ref = &lhs; |
| 1165 | AstNode *lhs = trans_expr(c, true, child_block, stmt->getLHS(), TransLValue); |
| 1166 | if (lhs == nullptr) return nullptr; |
| 1167 | AstNode *addr_of_lhs = trans_create_node_addr_of(c, false, false, lhs); |
| 1168 | // TODO: avoid name collisions with generated variable names |
| 1169 | Buf* tmp_var_name = buf_create_from_str("_ref"); |
| 1170 | AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, addr_of_lhs); |
| 1171 | child_block->data.block.statements.append(tmp_var_decl); |
| 1172 | |
| 1173 | // *_ref = result_type(operation_type(*_ref) >> u5(rhs)); |
| 1174 | |
| 1175 | AstNode *rhs = trans_expr(c, true, child_block, stmt->getRHS(), TransRValue); |
| 1176 | if (rhs == nullptr) return nullptr; |
| 1177 | AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs); |
| 1178 | |
| 1179 | AstNode *assign_statement = trans_create_node_bin_op(c, |
| 1180 | trans_create_node_prefix_op(c, PrefixOpDereference, |
| 1181 | trans_create_node_symbol(c, tmp_var_name)), |
| 1182 | BinOpTypeAssign, |
| 1183 | trans_c_cast(c, rhs_location, |
| 1184 | stmt->getComputationResultType(), |
| 1185 | trans_create_node_bin_op(c, |
| 1186 | trans_c_cast(c, rhs_location, |
| 1187 | stmt->getComputationLHSType(), |
| 1188 | trans_create_node_prefix_op(c, PrefixOpDereference, |
| 1189 | trans_create_node_symbol(c, tmp_var_name))), |
| 1190 | bin_op, |
| 1191 | coerced_rhs))); |
| 1192 | child_block->data.block.statements.append(assign_statement); |
| 1193 | |
| 1194 | if (result_used) { |
| 1195 | // *_ref |
| 1196 | child_block->data.block.statements.append( |
| 1197 | trans_create_node_prefix_op(c, PrefixOpDereference, |
| 1198 | trans_create_node_symbol(c, tmp_var_name))); |
| 1199 | child_block->data.block.last_statement_is_result_expression = true; |
| 1200 | } |
| 1201 | |
| 1202 | return child_block; |
| 1203 | } |
| 1204 | } |
| 1205 | case BO_AndAssign: |
| 1206 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_AndAssign"); |
| 1207 | return nullptr; |
| 1208 | case BO_XorAssign: |
| 1209 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_XorAssign"); |
| 1210 | return nullptr; |
| 1211 | case BO_OrAssign: |
| 1212 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_OrAssign"); |
| 1213 | return nullptr; |
| 1214 | case BO_PtrMemD: |
| 1215 | case BO_PtrMemI: |
| 1216 | case BO_Assign: |
| 1217 | case BO_Mul: |
| 1218 | case BO_Div: |
| 1219 | case BO_Rem: |
| 1220 | case BO_Add: |
| 1221 | case BO_Sub: |
| 1222 | case BO_Shl: |
| 1223 | case BO_Shr: |
| 1224 | case BO_LT: |
| 1225 | case BO_GT: |
| 1226 | case BO_LE: |
| 1227 | case BO_GE: |
| 1228 | case BO_EQ: |
| 1229 | case BO_NE: |
| 1230 | case BO_And: |
| 1231 | case BO_Xor: |
| 1232 | case BO_Or: |
| 1233 | case BO_LAnd: |
| 1234 | case BO_LOr: |
| 1235 | case BO_Comma: |
| 1236 | zig_panic("compound assign expected to be handled by binary operator"); |
| 1237 | } |
| 1238 | |
| 1239 | zig_unreachable(); |
| 1240 | } |
| 1241 | |
| 880 | 1242 | static AstNode *trans_implicit_cast_expr(Context *c, AstNode *block, ImplicitCastExpr *stmt) { |
| 881 | 1243 | switch (stmt->getCastKind()) { |
| 882 | 1244 | case CK_LValueToRValue: |
| 883 | | return trans_expr(c, block, stmt->getSubExpr()); |
| 1245 | return trans_expr(c, true, block, stmt->getSubExpr(), TransRValue); |
| 884 | 1246 | case CK_IntegralCast: |
| 885 | 1247 | { |
| 886 | | AstNode *node = trans_create_node_builtin_fn_call_str(c, "bitCast"); |
| 887 | | |
| 888 | | AstNode *result_type_node = trans_qual_type(c, stmt->getType(), stmt->getExprLoc()); |
| 889 | | if (result_type_node == nullptr) |
| 1248 | AstNode *target_node = trans_expr(c, true, block, stmt->getSubExpr(), TransRValue); |
| 1249 | if (target_node == nullptr) |
| 890 | 1250 | return nullptr; |
| 891 | | |
| 892 | | AstNode *target_node = trans_expr(c, block, stmt->getSubExpr()); |
| 1251 | return trans_c_cast(c, stmt->getExprLoc(), stmt->getType(), target_node); |
| 1252 | } |
| 1253 | case CK_FunctionToPointerDecay: |
| 1254 | case CK_ArrayToPointerDecay: |
| 1255 | { |
| 1256 | AstNode *target_node = trans_expr(c, true, block, stmt->getSubExpr(), TransRValue); |
| 893 | 1257 | if (target_node == nullptr) |
| 894 | 1258 | return nullptr; |
| 1259 | return target_node; |
| 1260 | } |
| 1261 | case CK_BitCast: |
| 1262 | { |
| 1263 | AstNode *target_node = trans_expr(c, true, block, stmt->getSubExpr(), TransRValue); |
| 1264 | if (target_node == nullptr) |
| 1265 | return nullptr; |
| 1266 | |
| 1267 | AstNode *dest_type_node = trans_qual_type(c, stmt->getType(), stmt->getLocStart()); |
| 895 | 1268 | |
| 896 | | node->data.fn_call_expr.params.append(result_type_node); |
| 1269 | AstNode *node = trans_create_node_builtin_fn_call_str(c, "ptrCast"); |
| 1270 | node->data.fn_call_expr.params.append(dest_type_node); |
| 897 | 1271 | node->data.fn_call_expr.params.append(target_node); |
| 898 | 1272 | return node; |
| 899 | 1273 | } |
| 900 | 1274 | case CK_Dependent: |
| 901 | 1275 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_Dependent"); |
| 902 | 1276 | return nullptr; |
| 903 | | case CK_BitCast: |
| 904 | | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_BitCast"); |
| 905 | | return nullptr; |
| 906 | 1277 | case CK_LValueBitCast: |
| 907 | 1278 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_LValueBitCast"); |
| 908 | 1279 | return nullptr; |
| ... | ... | @@ -924,12 +1295,6 @@ static AstNode *trans_implicit_cast_expr(Context *c, AstNode *block, ImplicitCas |
| 924 | 1295 | case CK_ToUnion: |
| 925 | 1296 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ToUnion"); |
| 926 | 1297 | return nullptr; |
| 927 | | case CK_ArrayToPointerDecay: |
| 928 | | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ArrayToPointerDecay"); |
| 929 | | return nullptr; |
| 930 | | case CK_FunctionToPointerDecay: |
| 931 | | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FunctionToPointerDecay"); |
| 932 | | return nullptr; |
| 933 | 1298 | case CK_NullToPointer: |
| 934 | 1299 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_NullToPointer"); |
| 935 | 1300 | return nullptr; |
| ... | ... | @@ -1069,17 +1434,44 @@ static AstNode *trans_implicit_cast_expr(Context *c, AstNode *block, ImplicitCas |
| 1069 | 1434 | zig_unreachable(); |
| 1070 | 1435 | } |
| 1071 | 1436 | |
| 1072 | | static AstNode *trans_decl_ref_expr(Context *c, DeclRefExpr *stmt) { |
| 1437 | static AstNode *trans_decl_ref_expr(Context *c, DeclRefExpr *stmt, TransLRValue lrval) { |
| 1073 | 1438 | ValueDecl *value_decl = stmt->getDecl(); |
| 1074 | | const char *name = decl_name(value_decl); |
| 1075 | | return trans_create_node_symbol_str(c, name); |
| 1439 | Buf *symbol_name = buf_create_from_str(decl_name(value_decl)); |
| 1440 | if (lrval == TransLValue) { |
| 1441 | c->ptr_params.put(symbol_name, true); |
| 1442 | } |
| 1443 | return trans_create_node_symbol(c, symbol_name); |
| 1076 | 1444 | } |
| 1077 | 1445 | |
| 1078 | | static AstNode *trans_unary_operator(Context *c, AstNode *block, UnaryOperator *stmt) { |
| 1446 | static AstNode *trans_unary_operator(Context *c, bool result_used, AstNode *block, UnaryOperator *stmt) { |
| 1079 | 1447 | switch (stmt->getOpcode()) { |
| 1080 | | case UO_PostInc: |
| 1081 | | emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_PostInc"); |
| 1082 | | return nullptr; |
| 1448 | case UO_PostInc: { |
| 1449 | Expr *op_expr = stmt->getSubExpr(); |
| 1450 | BinOpType bin_op = qual_type_has_wrapping_overflow(c, op_expr->getType()) |
| 1451 | ? BinOpTypeAssignPlusWrap |
| 1452 | : BinOpTypeAssignPlus; |
| 1453 | |
| 1454 | if (!result_used) { |
| 1455 | // common case |
| 1456 | // c: expr++ |
| 1457 | // zig: expr += 1 |
| 1458 | return trans_create_node_bin_op(c, |
| 1459 | trans_expr(c, true, block, op_expr, TransLValue), |
| 1460 | bin_op, |
| 1461 | trans_create_node_unsigned(c, 1)); |
| 1462 | } else { |
| 1463 | // worst case |
| 1464 | // c: expr++ |
| 1465 | // zig: { |
| 1466 | // zig: const _ref = &expr; |
| 1467 | // zig: const _tmp = *_ref; |
| 1468 | // zig: *_ref += 1; |
| 1469 | // zig: _tmp |
| 1470 | // zig: } |
| 1471 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_PostInc with result_used"); |
| 1472 | return nullptr; |
| 1473 | } |
| 1474 | } |
| 1083 | 1475 | case UO_PostDec: |
| 1084 | 1476 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_PostDec"); |
| 1085 | 1477 | return nullptr; |
| ... | ... | @@ -1101,11 +1493,11 @@ static AstNode *trans_unary_operator(Context *c, AstNode *block, UnaryOperator * |
| 1101 | 1493 | case UO_Minus: |
| 1102 | 1494 | { |
| 1103 | 1495 | Expr *op_expr = stmt->getSubExpr(); |
| 1104 | | if (c_is_signed_integer(c, op_expr->getType()) || c_is_float(c, op_expr->getType())) { |
| 1496 | if (!qual_type_has_wrapping_overflow(c, op_expr->getType())) { |
| 1105 | 1497 | AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr); |
| 1106 | 1498 | node->data.prefix_op_expr.prefix_op = PrefixOpNegation; |
| 1107 | 1499 | |
| 1108 | | node->data.prefix_op_expr.primary_expr = trans_expr(c, block, op_expr); |
| 1500 | node->data.prefix_op_expr.primary_expr = trans_expr(c, true, block, op_expr, TransRValue); |
| 1109 | 1501 | if (node->data.prefix_op_expr.primary_expr == nullptr) |
| 1110 | 1502 | return nullptr; |
| 1111 | 1503 | |
| ... | ... | @@ -1115,7 +1507,7 @@ static AstNode *trans_unary_operator(Context *c, AstNode *block, UnaryOperator * |
| 1115 | 1507 | AstNode *node = trans_create_node(c, NodeTypeBinOpExpr); |
| 1116 | 1508 | node->data.bin_op_expr.op1 = trans_create_node_unsigned(c, 0); |
| 1117 | 1509 | |
| 1118 | | node->data.bin_op_expr.op2 = trans_expr(c, block, op_expr); |
| 1510 | node->data.bin_op_expr.op2 = trans_expr(c, true, block, op_expr, TransRValue); |
| 1119 | 1511 | if (node->data.bin_op_expr.op2 == nullptr) |
| 1120 | 1512 | return nullptr; |
| 1121 | 1513 | |
| ... | ... | @@ -1157,7 +1549,7 @@ static AstNode *trans_local_declaration(Context *c, AstNode *block, DeclStmt *st |
| 1157 | 1549 | QualType qual_type = var_decl->getTypeSourceInfo()->getType(); |
| 1158 | 1550 | AstNode *init_node = nullptr; |
| 1159 | 1551 | if (var_decl->hasInit()) { |
| 1160 | | init_node = trans_expr(c, block, var_decl->getInit()); |
| 1552 | init_node = trans_expr(c, true, block, var_decl->getInit(), TransRValue); |
| 1161 | 1553 | if (init_node == nullptr) |
| 1162 | 1554 | return nullptr; |
| 1163 | 1555 | |
| ... | ... | @@ -1166,8 +1558,10 @@ static AstNode *trans_local_declaration(Context *c, AstNode *block, DeclStmt *st |
| 1166 | 1558 | if (type_node == nullptr) |
| 1167 | 1559 | return nullptr; |
| 1168 | 1560 | |
| 1169 | | AstNode *node = trans_create_node_var_decl(c, qual_type.isConstQualified(), |
| 1170 | | buf_create_from_str(decl_name(var_decl)), type_node, init_node); |
| 1561 | Buf *symbol_name = buf_create_from_str(decl_name(var_decl)); |
| 1562 | |
| 1563 | AstNode *node = trans_create_node_var_decl_local(c, qual_type.isConstQualified(), |
| 1564 | symbol_name, type_node, init_node); |
| 1171 | 1565 | block->data.block.statements.append(node); |
| 1172 | 1566 | continue; |
| 1173 | 1567 | } |
| ... | ... | @@ -1398,18 +1792,112 @@ static AstNode *trans_local_declaration(Context *c, AstNode *block, DeclStmt *st |
| 1398 | 1792 | static AstNode *trans_while_loop(Context *c, AstNode *block, WhileStmt *stmt) { |
| 1399 | 1793 | AstNode *while_node = trans_create_node(c, NodeTypeWhileExpr); |
| 1400 | 1794 | |
| 1401 | | while_node->data.while_expr.condition = trans_expr(c, block, stmt->getCond()); |
| 1795 | while_node->data.while_expr.condition = trans_expr(c, true, block, stmt->getCond(), TransRValue); |
| 1402 | 1796 | if (while_node->data.while_expr.condition == nullptr) |
| 1403 | 1797 | return nullptr; |
| 1404 | 1798 | |
| 1405 | | while_node->data.while_expr.body = trans_stmt(c, block, stmt->getBody()); |
| 1799 | while_node->data.while_expr.body = trans_stmt(c, false, block, stmt->getBody(), TransRValue); |
| 1406 | 1800 | if (while_node->data.while_expr.body == nullptr) |
| 1407 | 1801 | return nullptr; |
| 1408 | 1802 | |
| 1409 | 1803 | return while_node; |
| 1410 | 1804 | } |
| 1411 | 1805 | |
| 1412 | | static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) { |
| 1806 | static AstNode *trans_if_statement(Context *c, AstNode *block, IfStmt *stmt) { |
| 1807 | // if (c) t |
| 1808 | // if (c) t else e |
| 1809 | AstNode *if_node = trans_create_node(c, NodeTypeIfBoolExpr); |
| 1810 | |
| 1811 | // TODO: condition != 0 |
| 1812 | AstNode *condition_node = trans_expr(c, true, block, stmt->getCond(), TransRValue); |
| 1813 | if (condition_node == nullptr) |
| 1814 | return nullptr; |
| 1815 | if_node->data.if_bool_expr.condition = condition_node; |
| 1816 | |
| 1817 | if_node->data.if_bool_expr.then_block = trans_stmt(c, false, block, stmt->getThen(), TransRValue); |
| 1818 | if (if_node->data.if_bool_expr.then_block == nullptr) |
| 1819 | return nullptr; |
| 1820 | |
| 1821 | if (stmt->getElse() != nullptr) { |
| 1822 | if_node->data.if_bool_expr.else_node = trans_stmt(c, false, block, stmt->getElse(), TransRValue); |
| 1823 | if (if_node->data.if_bool_expr.else_node == nullptr) |
| 1824 | return nullptr; |
| 1825 | } |
| 1826 | |
| 1827 | return if_node; |
| 1828 | } |
| 1829 | |
| 1830 | static AstNode *trans_call_expr(Context *c, bool result_used, AstNode *block, CallExpr *stmt) { |
| 1831 | AstNode *node = trans_create_node(c, NodeTypeFnCallExpr); |
| 1832 | node->data.fn_call_expr.fn_ref_expr = trans_expr(c, true, block, stmt->getCallee(), TransRValue); |
| 1833 | if (node->data.fn_call_expr.fn_ref_expr == nullptr) |
| 1834 | return nullptr; |
| 1835 | |
| 1836 | unsigned num_args = stmt->getNumArgs(); |
| 1837 | Expr **args = stmt->getArgs(); |
| 1838 | for (unsigned i = 0; i < num_args; i += 1) { |
| 1839 | AstNode *arg_node = trans_expr(c, true, block, args[i], TransRValue); |
| 1840 | if (arg_node == nullptr) |
| 1841 | return nullptr; |
| 1842 | |
| 1843 | node->data.fn_call_expr.params.append(arg_node); |
| 1844 | } |
| 1845 | |
| 1846 | return node; |
| 1847 | } |
| 1848 | |
| 1849 | static AstNode *trans_member_expr(Context *c, AstNode *block, MemberExpr *stmt) { |
| 1850 | AstNode *container_node = trans_expr(c, true, block, stmt->getBase(), TransRValue); |
| 1851 | if (container_node == nullptr) |
| 1852 | return nullptr; |
| 1853 | |
| 1854 | if (stmt->isArrow()) { |
| 1855 | container_node = trans_create_node_unwrap_null(c, container_node); |
| 1856 | } |
| 1857 | |
| 1858 | const char *name = decl_name(stmt->getMemberDecl()); |
| 1859 | |
| 1860 | AstNode *node = trans_create_node_field_access_str(c, container_node, name); |
| 1861 | return node; |
| 1862 | } |
| 1863 | |
| 1864 | static AstNode *trans_array_subscript_expr(Context *c, AstNode *block, ArraySubscriptExpr *stmt) { |
| 1865 | AstNode *container_node = trans_expr(c, true, block, stmt->getBase(), TransRValue); |
| 1866 | if (container_node == nullptr) |
| 1867 | return nullptr; |
| 1868 | |
| 1869 | AstNode *idx_node = trans_expr(c, true, block, stmt->getIdx(), TransRValue); |
| 1870 | if (idx_node == nullptr) |
| 1871 | return nullptr; |
| 1872 | |
| 1873 | |
| 1874 | AstNode *node = trans_create_node(c, NodeTypeArrayAccessExpr); |
| 1875 | node->data.array_access_expr.array_ref_expr = container_node; |
| 1876 | node->data.array_access_expr.subscript = idx_node; |
| 1877 | return node; |
| 1878 | } |
| 1879 | |
| 1880 | static AstNode *trans_c_style_cast_expr(Context *c, bool result_used, AstNode *block, |
| 1881 | CStyleCastExpr *stmt, TransLRValue lrvalue) |
| 1882 | { |
| 1883 | AstNode *sub_expr_node = trans_expr(c, result_used, block, stmt->getSubExpr(), lrvalue); |
| 1884 | if (sub_expr_node == nullptr) |
| 1885 | return nullptr; |
| 1886 | |
| 1887 | return trans_c_cast(c, stmt->getLocStart(), stmt->getType(), sub_expr_node); |
| 1888 | } |
| 1889 | |
| 1890 | static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, AstNode *block, UnaryExprOrTypeTraitExpr *stmt) { |
| 1891 | AstNode *type_node = trans_qual_type(c, stmt->getTypeOfArgument(), stmt->getLocStart()); |
| 1892 | if (type_node == nullptr) |
| 1893 | return nullptr; |
| 1894 | |
| 1895 | AstNode *node = trans_create_node_builtin_fn_call_str(c, "sizeOf"); |
| 1896 | node->data.fn_call_expr.params.append(type_node); |
| 1897 | return node; |
| 1898 | } |
| 1899 | |
| 1900 | static AstNode *trans_stmt(Context *c, bool result_used, AstNode *block, Stmt *stmt, TransLRValue lrvalue) { |
| 1413 | 1901 | Stmt::StmtClass sc = stmt->getStmtClass(); |
| 1414 | 1902 | switch (sc) { |
| 1415 | 1903 | case Stmt::ReturnStmtClass: |
| ... | ... | @@ -1419,19 +1907,35 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) { |
| 1419 | 1907 | case Stmt::IntegerLiteralClass: |
| 1420 | 1908 | return trans_integer_literal(c, (IntegerLiteral *)stmt); |
| 1421 | 1909 | case Stmt::ConditionalOperatorClass: |
| 1422 | | return trans_conditional_operator(c, block, (ConditionalOperator *)stmt); |
| 1910 | return trans_conditional_operator(c, result_used, block, (ConditionalOperator *)stmt); |
| 1423 | 1911 | case Stmt::BinaryOperatorClass: |
| 1424 | | return trans_binary_operator(c, block, (BinaryOperator *)stmt); |
| 1912 | return trans_binary_operator(c, result_used, block, (BinaryOperator *)stmt); |
| 1913 | case Stmt::CompoundAssignOperatorClass: |
| 1914 | return trans_compound_assign_operator(c, result_used, block, (CompoundAssignOperator *)stmt); |
| 1425 | 1915 | case Stmt::ImplicitCastExprClass: |
| 1426 | 1916 | return trans_implicit_cast_expr(c, block, (ImplicitCastExpr *)stmt); |
| 1427 | 1917 | case Stmt::DeclRefExprClass: |
| 1428 | | return trans_decl_ref_expr(c, (DeclRefExpr *)stmt); |
| 1918 | return trans_decl_ref_expr(c, (DeclRefExpr *)stmt, lrvalue); |
| 1429 | 1919 | case Stmt::UnaryOperatorClass: |
| 1430 | | return trans_unary_operator(c, block, (UnaryOperator *)stmt); |
| 1920 | return trans_unary_operator(c, result_used, block, (UnaryOperator *)stmt); |
| 1431 | 1921 | case Stmt::DeclStmtClass: |
| 1432 | 1922 | return trans_local_declaration(c, block, (DeclStmt *)stmt); |
| 1433 | 1923 | case Stmt::WhileStmtClass: |
| 1434 | 1924 | return trans_while_loop(c, block, (WhileStmt *)stmt); |
| 1925 | case Stmt::IfStmtClass: |
| 1926 | return trans_if_statement(c, block, (IfStmt *)stmt); |
| 1927 | case Stmt::CallExprClass: |
| 1928 | return trans_call_expr(c, result_used, block, (CallExpr *)stmt); |
| 1929 | case Stmt::NullStmtClass: |
| 1930 | return skip_add_to_block_node; |
| 1931 | case Stmt::MemberExprClass: |
| 1932 | return trans_member_expr(c, block, (MemberExpr *)stmt); |
| 1933 | case Stmt::ArraySubscriptExprClass: |
| 1934 | return trans_array_subscript_expr(c, block, (ArraySubscriptExpr *)stmt); |
| 1935 | case Stmt::CStyleCastExprClass: |
| 1936 | return trans_c_style_cast_expr(c, result_used, block, (CStyleCastExpr *)stmt, lrvalue); |
| 1937 | case Stmt::UnaryExprOrTypeTraitExprClass: |
| 1938 | return trans_unary_expr_or_type_trait_expr(c, block, (UnaryExprOrTypeTraitExpr *)stmt); |
| 1435 | 1939 | case Stmt::CaseStmtClass: |
| 1436 | 1940 | emit_warning(c, stmt->getLocStart(), "TODO handle C CaseStmtClass"); |
| 1437 | 1941 | return nullptr; |
| ... | ... | @@ -1492,9 +1996,6 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) { |
| 1492 | 1996 | case Stmt::ArrayInitLoopExprClass: |
| 1493 | 1997 | emit_warning(c, stmt->getLocStart(), "TODO handle C ArrayInitLoopExprClass"); |
| 1494 | 1998 | return nullptr; |
| 1495 | | case Stmt::ArraySubscriptExprClass: |
| 1496 | | emit_warning(c, stmt->getLocStart(), "TODO handle C ArraySubscriptExprClass"); |
| 1497 | | return nullptr; |
| 1498 | 1999 | case Stmt::ArrayTypeTraitExprClass: |
| 1499 | 2000 | emit_warning(c, stmt->getLocStart(), "TODO handle C ArrayTypeTraitExprClass"); |
| 1500 | 2001 | return nullptr; |
| ... | ... | @@ -1504,9 +2005,6 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) { |
| 1504 | 2005 | case Stmt::AtomicExprClass: |
| 1505 | 2006 | emit_warning(c, stmt->getLocStart(), "TODO handle C AtomicExprClass"); |
| 1506 | 2007 | return nullptr; |
| 1507 | | case Stmt::CompoundAssignOperatorClass: |
| 1508 | | emit_warning(c, stmt->getLocStart(), "TODO handle C CompoundAssignOperatorClass"); |
| 1509 | | return nullptr; |
| 1510 | 2008 | case Stmt::BlockExprClass: |
| 1511 | 2009 | emit_warning(c, stmt->getLocStart(), "TODO handle C BlockExprClass"); |
| 1512 | 2010 | return nullptr; |
| ... | ... | @@ -1573,13 +2071,11 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) { |
| 1573 | 2071 | case Stmt::CXXUuidofExprClass: |
| 1574 | 2072 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXUuidofExprClass"); |
| 1575 | 2073 | return nullptr; |
| 1576 | | case Stmt::CallExprClass: |
| 1577 | | emit_warning(c, stmt->getLocStart(), "TODO handle C CallExprClass"); |
| 1578 | | return nullptr; |
| 1579 | 2074 | case Stmt::CUDAKernelCallExprClass: |
| 1580 | 2075 | emit_warning(c, stmt->getLocStart(), "TODO handle C CUDAKernelCallExprClass"); |
| 1581 | 2076 | return nullptr; |
| 1582 | 2077 | case Stmt::CXXMemberCallExprClass: |
| 2078 | (void)result_used; |
| 1583 | 2079 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXMemberCallExprClass"); |
| 1584 | 2080 | return nullptr; |
| 1585 | 2081 | case Stmt::CXXOperatorCallExprClass: |
| ... | ... | @@ -1588,9 +2084,6 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) { |
| 1588 | 2084 | case Stmt::UserDefinedLiteralClass: |
| 1589 | 2085 | emit_warning(c, stmt->getLocStart(), "TODO handle C UserDefinedLiteralClass"); |
| 1590 | 2086 | return nullptr; |
| 1591 | | case Stmt::CStyleCastExprClass: |
| 1592 | | emit_warning(c, stmt->getLocStart(), "TODO handle C CStyleCastExprClass"); |
| 1593 | | return nullptr; |
| 1594 | 2087 | case Stmt::CXXFunctionalCastExprClass: |
| 1595 | 2088 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXFunctionalCastExprClass"); |
| 1596 | 2089 | return nullptr; |
| ... | ... | @@ -1681,9 +2174,6 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) { |
| 1681 | 2174 | case Stmt::MaterializeTemporaryExprClass: |
| 1682 | 2175 | emit_warning(c, stmt->getLocStart(), "TODO handle C MaterializeTemporaryExprClass"); |
| 1683 | 2176 | return nullptr; |
| 1684 | | case Stmt::MemberExprClass: |
| 1685 | | emit_warning(c, stmt->getLocStart(), "TODO handle C MemberExprClass"); |
| 1686 | | return nullptr; |
| 1687 | 2177 | case Stmt::NoInitExprClass: |
| 1688 | 2178 | emit_warning(c, stmt->getLocStart(), "TODO handle C NoInitExprClass"); |
| 1689 | 2179 | return nullptr; |
| ... | ... | @@ -1751,8 +2241,7 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) { |
| 1751 | 2241 | emit_warning(c, stmt->getLocStart(), "TODO handle C PackExpansionExprClass"); |
| 1752 | 2242 | return nullptr; |
| 1753 | 2243 | case Stmt::ParenExprClass: |
| 1754 | | emit_warning(c, stmt->getLocStart(), "TODO handle C ParenExprClass"); |
| 1755 | | return nullptr; |
| 2244 | return trans_expr(c, result_used, block, ((ParenExpr*)stmt)->getSubExpr(), lrvalue); |
| 1756 | 2245 | case Stmt::ParenListExprClass: |
| 1757 | 2246 | emit_warning(c, stmt->getLocStart(), "TODO handle C ParenListExprClass"); |
| 1758 | 2247 | return nullptr; |
| ... | ... | @@ -1786,9 +2275,6 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) { |
| 1786 | 2275 | case Stmt::TypoExprClass: |
| 1787 | 2276 | emit_warning(c, stmt->getLocStart(), "TODO handle C TypoExprClass"); |
| 1788 | 2277 | return nullptr; |
| 1789 | | case Stmt::UnaryExprOrTypeTraitExprClass: |
| 1790 | | emit_warning(c, stmt->getLocStart(), "TODO handle C UnaryExprOrTypeTraitExprClass"); |
| 1791 | | return nullptr; |
| 1792 | 2278 | case Stmt::VAArgExprClass: |
| 1793 | 2279 | emit_warning(c, stmt->getLocStart(), "TODO handle C VAArgExprClass"); |
| 1794 | 2280 | return nullptr; |
| ... | ... | @@ -1798,9 +2284,6 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) { |
| 1798 | 2284 | case Stmt::GotoStmtClass: |
| 1799 | 2285 | emit_warning(c, stmt->getLocStart(), "TODO handle C GotoStmtClass"); |
| 1800 | 2286 | return nullptr; |
| 1801 | | case Stmt::IfStmtClass: |
| 1802 | | emit_warning(c, stmt->getLocStart(), "TODO handle C IfStmtClass"); |
| 1803 | | return nullptr; |
| 1804 | 2287 | case Stmt::IndirectGotoStmtClass: |
| 1805 | 2288 | emit_warning(c, stmt->getLocStart(), "TODO handle C IndirectGotoStmtClass"); |
| 1806 | 2289 | return nullptr; |
| ... | ... | @@ -1810,9 +2293,6 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) { |
| 1810 | 2293 | case Stmt::MSDependentExistsStmtClass: |
| 1811 | 2294 | emit_warning(c, stmt->getLocStart(), "TODO handle C MSDependentExistsStmtClass"); |
| 1812 | 2295 | return nullptr; |
| 1813 | | case Stmt::NullStmtClass: |
| 1814 | | emit_warning(c, stmt->getLocStart(), "TODO handle C NullStmtClass"); |
| 1815 | | return nullptr; |
| 1816 | 2296 | case Stmt::OMPAtomicDirectiveClass: |
| 1817 | 2297 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPAtomicDirectiveClass"); |
| 1818 | 2298 | return nullptr; |
| ... | ... | @@ -2025,36 +2505,65 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { |
| 2025 | 2505 | AstNode *param_node = proto_node->data.fn_proto.params.at(i); |
| 2026 | 2506 | const ParmVarDecl *param = fn_decl->getParamDecl(i); |
| 2027 | 2507 | const char *name = decl_name(param); |
| 2028 | | if (strlen(name) == 0) { |
| 2029 | | Buf *proto_param_name = param_node->data.param_decl.name; |
| 2508 | Buf *proto_param_name; |
| 2509 | if (strlen(name) != 0) { |
| 2510 | proto_param_name = buf_create_from_str(name); |
| 2511 | } else { |
| 2512 | proto_param_name = param_node->data.param_decl.name; |
| 2030 | 2513 | if (proto_param_name == nullptr) { |
| 2031 | | param_node->data.param_decl.name = buf_sprintf("arg%" ZIG_PRI_usize "", i); |
| 2032 | | } else { |
| 2033 | | param_node->data.param_decl.name = proto_param_name; |
| 2514 | proto_param_name = buf_sprintf("arg%" ZIG_PRI_usize "", i); |
| 2034 | 2515 | } |
| 2035 | | } else { |
| 2036 | | param_node->data.param_decl.name = buf_create_from_str(name); |
| 2037 | 2516 | } |
| 2517 | param_node->data.param_decl.name = proto_param_name; |
| 2518 | } |
| 2519 | |
| 2520 | if (!fn_decl->hasBody()) { |
| 2521 | // just a prototype |
| 2522 | c->root->data.root.top_level_decls.append(proto_node); |
| 2523 | return; |
| 2038 | 2524 | } |
| 2039 | 2525 | |
| 2040 | | if (fn_decl->hasBody()) { |
| 2041 | | Stmt *body = fn_decl->getBody(); |
| 2526 | // actual function definition with body |
| 2527 | c->ptr_params.clear(); |
| 2528 | Stmt *body = fn_decl->getBody(); |
| 2529 | AstNode *actual_body_node = trans_stmt(c, false, nullptr, body, TransRValue); |
| 2530 | assert(actual_body_node != skip_add_to_block_node); |
| 2531 | if (actual_body_node == nullptr) { |
| 2532 | emit_warning(c, fn_decl->getLocation(), "unable to translate function"); |
| 2533 | return; |
| 2534 | } |
| 2042 | 2535 | |
| 2043 | | AstNode *fn_def_node = trans_create_node(c, NodeTypeFnDef); |
| 2044 | | fn_def_node->data.fn_def.fn_proto = proto_node; |
| 2045 | | fn_def_node->data.fn_def.body = trans_stmt(c, nullptr, body); |
| 2046 | | assert(fn_def_node->data.fn_def.body != skip_add_to_block_node); |
| 2047 | | if (fn_def_node->data.fn_def.body == nullptr) { |
| 2048 | | emit_warning(c, fn_decl->getLocation(), "unable to translate function"); |
| 2049 | | return; |
| 2536 | // it worked |
| 2537 | |
| 2538 | assert(actual_body_node->type == NodeTypeBlock); |
| 2539 | AstNode *body_node_with_param_inits = trans_create_node(c, NodeTypeBlock); |
| 2540 | |
| 2541 | for (size_t i = 0; i < proto_node->data.fn_proto.params.length; i += 1) { |
| 2542 | AstNode *param_node = proto_node->data.fn_proto.params.at(i); |
| 2543 | Buf *good_name = param_node->data.param_decl.name; |
| 2544 | |
| 2545 | if (c->ptr_params.maybe_get(good_name) != nullptr) { |
| 2546 | // TODO: avoid name collisions |
| 2547 | Buf *mangled_name = buf_sprintf("_arg_%s", buf_ptr(good_name)); |
| 2548 | param_node->data.param_decl.name = mangled_name; |
| 2549 | |
| 2550 | // var c_name = _mangled_name; |
| 2551 | AstNode *parameter_init = trans_create_node_var_decl_local(c, false, good_name, nullptr, trans_create_node_symbol(c, mangled_name)); |
| 2552 | |
| 2553 | body_node_with_param_inits->data.block.statements.append(parameter_init); |
| 2050 | 2554 | } |
| 2555 | } |
| 2051 | 2556 | |
| 2052 | | proto_node->data.fn_proto.fn_def_node = fn_def_node; |
| 2053 | | c->root->data.root.top_level_decls.append(fn_def_node); |
| 2054 | | return; |
| 2557 | for (size_t i = 0; i < actual_body_node->data.block.statements.length; i += 1) { |
| 2558 | body_node_with_param_inits->data.block.statements.append(actual_body_node->data.block.statements.at(i)); |
| 2055 | 2559 | } |
| 2056 | 2560 | |
| 2057 | | c->root->data.root.top_level_decls.append(proto_node); |
| 2561 | AstNode *fn_def_node = trans_create_node(c, NodeTypeFnDef); |
| 2562 | fn_def_node->data.fn_def.fn_proto = proto_node; |
| 2563 | fn_def_node->data.fn_def.body = body_node_with_param_inits; |
| 2564 | |
| 2565 | proto_node->data.fn_proto.fn_def_node = fn_def_node; |
| 2566 | c->root->data.root.top_level_decls.append(fn_def_node); |
| 2058 | 2567 | } |
| 2059 | 2568 | |
| 2060 | 2569 | static AstNode *resolve_typdef_as_builtin(Context *c, const TypedefNameDecl *typedef_decl, const char *primitive_name) { |
| ... | ... | @@ -2190,9 +2699,14 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) { |
| 2190 | 2699 | |
| 2191 | 2700 | // in C each enum value is in the global namespace. so we put them there too. |
| 2192 | 2701 | // at this point we can rely on the enum emitting successfully |
| 2193 | | AstNode *field_access_node = trans_create_node_field_access(c, |
| 2194 | | trans_create_node_symbol(c, full_type_name), field_name); |
| 2195 | | add_global_var(c, enum_val_name, field_access_node); |
| 2702 | if (is_anonymous) { |
| 2703 | AstNode *lit_node = trans_create_node_unsigned(c, i); |
| 2704 | add_global_var(c, enum_val_name, lit_node); |
| 2705 | } else { |
| 2706 | AstNode *field_access_node = trans_create_node_field_access(c, |
| 2707 | trans_create_node_symbol(c, full_type_name), field_name); |
| 2708 | add_global_var(c, enum_val_name, field_access_node); |
| 2709 | } |
| 2196 | 2710 | } |
| 2197 | 2711 | |
| 2198 | 2712 | if (is_anonymous) { |
| ... | ... | @@ -2376,7 +2890,7 @@ static void visit_var_decl(Context *c, const VarDecl *var_decl) { |
| 2376 | 2890 | init_node = trans_create_node_apint(c, ap_value->getInt()); |
| 2377 | 2891 | break; |
| 2378 | 2892 | case APValue::Uninitialized: |
| 2379 | | init_node = trans_create_node_symbol_str(c, "undefined"); |
| 2893 | init_node = trans_create_node(c, NodeTypeUndefinedLiteral); |
| 2380 | 2894 | break; |
| 2381 | 2895 | case APValue::Float: |
| 2382 | 2896 | case APValue::ComplexInt: |
| ... | ... | @@ -2393,16 +2907,16 @@ static void visit_var_decl(Context *c, const VarDecl *var_decl) { |
| 2393 | 2907 | return; |
| 2394 | 2908 | } |
| 2395 | 2909 | } else { |
| 2396 | | init_node = trans_create_node_symbol_str(c, "undefined"); |
| 2910 | init_node = trans_create_node(c, NodeTypeUndefinedLiteral); |
| 2397 | 2911 | } |
| 2398 | 2912 | |
| 2399 | | AstNode *var_node = trans_create_node_var_decl(c, is_const, name, var_type, init_node); |
| 2913 | AstNode *var_node = trans_create_node_var_decl_global(c, is_const, name, var_type, init_node); |
| 2400 | 2914 | c->root->data.root.top_level_decls.append(var_node); |
| 2401 | 2915 | return; |
| 2402 | 2916 | } |
| 2403 | 2917 | |
| 2404 | 2918 | if (is_extern) { |
| 2405 | | AstNode *var_node = trans_create_node_var_decl(c, is_const, name, var_type, nullptr); |
| 2919 | AstNode *var_node = trans_create_node_var_decl_global(c, is_const, name, var_type, nullptr); |
| 2406 | 2920 | var_node->data.variable_declaration.is_extern = true; |
| 2407 | 2921 | c->root->data.root.top_level_decls.append(var_node); |
| 2408 | 2922 | return; |
| ... | ... | @@ -2663,6 +3177,7 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const ch |
| 2663 | 3177 | c->visib_mod = VisibModPub; |
| 2664 | 3178 | c->decl_table.init(8); |
| 2665 | 3179 | c->macro_table.init(8); |
| 3180 | c->ptr_params.init(8); |
| 2666 | 3181 | c->codegen = codegen; |
| 2667 | 3182 | c->source_node = source_node; |
| 2668 | 3183 | |