| ... | @@ -49,6 +49,8 @@ struct Context { | ... | @@ -49,6 +49,8 @@ struct Context { |
| 49 | | 49 | |
| 50 | CodeGen *codegen; | 50 | CodeGen *codegen; |
| 51 | ASTContext *ctx; | 51 | ASTContext *ctx; |
| | 52 | |
| | 53 | HashMap<Buf *, bool, buf_hash, buf_eql_buf> ptr_params; |
| 52 | }; | 54 | }; |
| 53 | | 55 | |
| 54 | static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl); | 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,13 +128,27 @@ static AstNode *trans_create_node_opaque(Context *c) { |
| 126 | return trans_create_node_builtin_fn_call_str(c, "OpaqueType"); | 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 | static AstNode *trans_create_node_field_access(Context *c, AstNode *container, Buf *field_name) { | 138 | static AstNode *trans_create_node_field_access(Context *c, AstNode *container, Buf *field_name) { |
| 130 | AstNode *node = trans_create_node(c, NodeTypeFieldAccessExpr); | 139 | AstNode *node = trans_create_node(c, NodeTypeFieldAccessExpr); |
| | 140 | 	if (container->type == NodeTypeSymbol) { |
| | 141 | 		assert(container->data.symbol_expr.symbol != nullptr); |
| | 142 | 	} |
| 131 | node->data.field_access_expr.struct_expr = container; | 143 | node->data.field_access_expr.struct_expr = container; |
| 132 | node->data.field_access_expr.field_name = field_name; | 144 | node->data.field_access_expr.field_name = field_name; |
| 133 | return node; | 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 | static AstNode *trans_create_node_prefix_op(Context *c, PrefixOp op, AstNode *child_node) { | 152 | static AstNode *trans_create_node_prefix_op(Context *c, PrefixOp op, AstNode *child_node) { |
| 137 | AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr); | 153 | AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr); |
| 138 | node->data.prefix_op_expr.prefix_op = op; | 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,6 +156,22 @@ static AstNode *trans_create_node_prefix_op(Context *c, PrefixOp op, AstNode *ch |
| 140 | return node; | 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 | static AstNode *trans_create_node_addr_of(Context *c, bool is_const, bool is_volatile, AstNode *child_node) { | 175 | static AstNode *trans_create_node_addr_of(Context *c, bool is_const, bool is_volatile, AstNode *child_node) { |
| 144 | AstNode *node = trans_create_node(c, NodeTypeAddrOfExpr); | 176 | AstNode *node = trans_create_node(c, NodeTypeAddrOfExpr); |
| 145 | node->data.addr_of_expr.is_const = is_const; | 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,6 +187,13 @@ static AstNode *trans_create_node_str_lit_c(Context *c, Buf *buf) { |
| 155 | return node; | 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 | static AstNode *trans_create_node_unsigned_negative(Context *c, uint64_t x, bool is_negative) { | 197 | static AstNode *trans_create_node_unsigned_negative(Context *c, uint64_t x, bool is_negative) { |
| 159 | AstNode *node = trans_create_node(c, NodeTypeIntLiteral); | 198 | AstNode *node = trans_create_node(c, NodeTypeIntLiteral); |
| 160 | node->data.int_literal.bigint = allocate<BigInt>(1); | 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,11 +227,11 @@ static AstNode *trans_create_node_array_type(Context *c, AstNode *size_node, Ast |
| 188 | return node; | 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, | 230 | static AstNode *trans_create_node_var_decl(Context *c, VisibMod visib_mod, bool is_const, Buf *var_name, |
| 192 | AstNode *init_node) | 231 | AstNode *type_node, AstNode *init_node) |
| 193 | { | 232 | { |
| 194 | AstNode *node = trans_create_node(c, NodeTypeVariableDeclaration); | 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 | node->data.variable_declaration.symbol = var_name; | 235 | node->data.variable_declaration.symbol = var_name; |
| 197 | node->data.variable_declaration.is_const = is_const; | 236 | node->data.variable_declaration.is_const = is_const; |
| 198 | node->data.variable_declaration.type = type_node; | 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,6 +239,18 @@ static AstNode *trans_create_node_var_decl(Context *c, bool is_const, Buf *var_n |
| 200 | return node; | 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 | static AstNode *trans_create_node_inline_fn(Context *c, Buf *fn_name, Buf *var_name, AstNode *src_proto_node) { | 255 | static AstNode *trans_create_node_inline_fn(Context *c, Buf *fn_name, Buf *var_name, AstNode *src_proto_node) { |
| 205 | AstNode *fn_def = trans_create_node(c, NodeTypeFnDef); | 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,6 +291,10 @@ static AstNode *trans_create_node_inline_fn(Context *c, Buf *fn_name, Buf *var_n |
| 240 | return fn_def; | 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 | static AstNode *get_global(Context *c, Buf *name) { | 298 | static AstNode *get_global(Context *c, Buf *name) { |
| 244 | for (size_t i = 0; i < c->root->data.root.top_level_decls.length; i += 1) { | 299 | for (size_t i = 0; i < c->root->data.root.top_level_decls.length; i += 1) { |
| 245 | AstNode *decl_node = c->root->data.root.top_level_decls.items[i]; | 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,7 +323,7 @@ static AstNode *get_global(Context *c, Buf *name) { |
| 268 | static AstNode *add_global_var(Context *c, Buf *var_name, AstNode *value_node) { | 323 | static AstNode *add_global_var(Context *c, Buf *var_name, AstNode *value_node) { |
| 269 | bool is_const = true; | 324 | bool is_const = true; |
| 270 | AstNode *type_node = nullptr; | 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 | c->root->data.root.top_level_decls.append(node); | 327 | c->root->data.root.top_level_decls.append(node); |
| 273 | return node; | 328 | return node; |
| 274 | } | 329 | } |
| ... | @@ -286,10 +341,96 @@ static AstNode *trans_create_node_apint(Context *c, const llvm::APSInt &aps_int) | ... | @@ -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 | static bool is_c_void_type(AstNode *node) { | 346 | static bool is_c_void_type(AstNode *node) { |
| 290 | return (node->type == NodeTypeSymbol && buf_eql_str(node->data.symbol_expr.symbol, "c_void")); | 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 | static bool qual_type_child_is_fn_proto(const QualType &qt) { | 434 | static bool qual_type_child_is_fn_proto(const QualType &qt) { |
| 294 | if (qt.getTypePtr()->getTypeClass() == Type::Paren) { | 435 | if (qt.getTypePtr()->getTypeClass() == Type::Paren) { |
| 295 | const ParenType *paren_type = static_cast<const ParenType *>(qt.getTypePtr()); | 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,8 +444,17 @@ static bool qual_type_child_is_fn_proto(const QualType &qt) { |
| 303 | return false; | 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 | static bool c_is_signed_integer(Context *c, QualType qt) { | 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 | if (c_type->getTypeClass() != Type::Builtin) | 458 | if (c_type->getTypeClass() != Type::Builtin) |
| 309 | return false; | 459 | return false; |
| 310 | const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(c_type); | 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,7 +473,7 @@ static bool c_is_signed_integer(Context *c, QualType qt) { |
| 323 | } | 473 | } |
| 324 | | 474 | |
| 325 | static bool c_is_unsigned_integer(Context *c, QualType qt) { | 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 | if (c_type->getTypeClass() != Type::Builtin) | 477 | if (c_type->getTypeClass() != Type::Builtin) |
| 328 | return false; | 478 | return false; |
| 329 | const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(c_type); | 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,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); | 513 | static bool qual_type_has_wrapping_overflow(Context *c, QualType qt) { |
| 364 | static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc); | 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 | static AstNode *const skip_add_to_block_node = (AstNode *) 0x2; | 529 | static AstNode *const skip_add_to_block_node = (AstNode *) 0x2; |
| 366 | | 530 | |
| 367 | static AstNode *trans_expr(Context *c, AstNode *block, Expr *expr) { | 531 | static AstNode *trans_expr(Context *c, bool result_used, AstNode *block, Expr *expr, TransLRValue lrval) { |
| 368 | return trans_stmt(c, block, expr); | 532 | return trans_stmt(c, result_used, block, expr, lrval); |
| 369 | } | 533 | } |
| 370 | | 534 | |
| 371 | static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &source_loc) { | 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,7 +873,7 @@ static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &s |
| 709 | static AstNode *trans_compound_stmt(Context *c, AstNode *parent, CompoundStmt *stmt) { | 873 | static AstNode *trans_compound_stmt(Context *c, AstNode *parent, CompoundStmt *stmt) { |
| 710 | AstNode *child_block = trans_create_node(c, NodeTypeBlock); | 874 | AstNode *child_block = trans_create_node(c, NodeTypeBlock); |
| 711 | for (CompoundStmt::body_iterator it = stmt->body_begin(), end_it = stmt->body_end(); it != end_it; ++it) { | 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 | if (child_node == nullptr) | 877 | if (child_node == nullptr) |
| 714 | return nullptr; | 878 | return nullptr; |
| 715 | if (child_node != skip_add_to_block_node) | 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,7 +889,7 @@ static AstNode *trans_return_stmt(Context *c, AstNode *block, ReturnStmt *stmt) |
| 725 | return nullptr; | 889 | return nullptr; |
| 726 | } else { | 890 | } else { |
| 727 | AstNode *return_node = trans_create_node(c, NodeTypeReturnExpr); | 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 | if (return_node->data.return_expr.expr == nullptr) | 893 | if (return_node->data.return_expr.expr == nullptr) |
| 730 | return nullptr; | 894 | return nullptr; |
| 731 | return return_node; | 895 | return return_node; |
| ... | @@ -741,44 +905,93 @@ static AstNode *trans_integer_literal(Context *c, IntegerLiteral *stmt) { | ... | @@ -741,44 +905,93 @@ static AstNode *trans_integer_literal(Context *c, IntegerLiteral *stmt) { |
| 741 | return trans_create_node_apint(c, result); | 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 | AstNode *node = trans_create_node(c, NodeTypeIfBoolExpr); | 909 | AstNode *node = trans_create_node(c, NodeTypeIfBoolExpr); |
| 746 | | 910 | |
| 747 | Expr *cond_expr = stmt->getCond(); | 911 | Expr *cond_expr = stmt->getCond(); |
| 748 | Expr *true_expr = stmt->getTrueExpr(); | 912 | Expr *true_expr = stmt->getTrueExpr(); |
| 749 | Expr *false_expr = stmt->getFalseExpr(); | 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 | if (node->data.if_bool_expr.condition == nullptr) | 916 | if (node->data.if_bool_expr.condition == nullptr) |
| 753 | return nullptr; | 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 | if (node->data.if_bool_expr.then_block == nullptr) | 920 | if (node->data.if_bool_expr.then_block == nullptr) |
| 757 | return nullptr; | 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 | if (node->data.if_bool_expr.else_node == nullptr) | 924 | if (node->data.if_bool_expr.else_node == nullptr) |
| 761 | return nullptr; | 925 | return nullptr; |
| 762 | | 926 | |
| 763 | return node; | 927 | return maybe_suppress_result(c, result_used, node); |
| 764 | } | 928 | } |
| 765 | | 929 | |
| 766 | static AstNode *trans_create_bin_op(Context *c, AstNode *block, Expr *lhs, BinOpType bin_op, Expr *rhs) { | 930 | static AstNode *trans_create_bin_op(Context *c, AstNode *block, Expr *lhs, BinOpType bin_op, Expr *rhs) { |
| 767 | AstNode *node = trans_create_node(c, NodeTypeBinOpExpr); | 931 | AstNode *node = trans_create_node(c, NodeTypeBinOpExpr); |
| 768 | node->data.bin_op_expr.bin_op = bin_op; | 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 | if (node->data.bin_op_expr.op1 == nullptr) | 935 | if (node->data.bin_op_expr.op1 == nullptr) |
| 772 | return nullptr; | 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 | if (node->data.bin_op_expr.op2 == nullptr) | 939 | if (node->data.bin_op_expr.op2 == nullptr) |
| 776 | return nullptr; | 940 | return nullptr; |
| 777 | | 941 | |
| 778 | return node; | 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 | switch (stmt->getOpcode()) { | 995 | switch (stmt->getOpcode()) { |
| 783 | case BO_PtrMemD: | 996 | case BO_PtrMemD: |
| 784 | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_PtrMemD"); | 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,20 +1000,47 @@ static AstNode *trans_binary_operator(Context *c, AstNode *block, BinaryOperator |
| 787 | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_PtrMemI"); | 1000 | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_PtrMemI"); |
| 788 | return nullptr; | 1001 | return nullptr; |
| 789 | case BO_Mul: | 1002 | case BO_Mul: |
| 790 | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_Mul"); | 1003 | return trans_create_bin_op(c, block, stmt->getLHS(), |
| 791 | return nullptr; | 1004 | qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeMultWrap : BinOpTypeMult, |
| | 1005 | stmt->getRHS()); |
| 792 | case BO_Div: | 1006 | case BO_Div: |
| 793 | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_Div"); | 1007 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) { |
| 794 | return nullptr; | 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 | case BO_Rem: | 1021 | case BO_Rem: |
| 796 | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_Rem"); | 1022 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) { |
| 797 | return nullptr; | 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 | case BO_Add: | 1036 | case BO_Add: |
| 799 | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_Add"); | 1037 | return trans_create_bin_op(c, block, stmt->getLHS(), |
| 800 | return nullptr; | 1038 | qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeAddWrap : BinOpTypeAdd, |
| | 1039 | stmt->getRHS()); |
| 801 | case BO_Sub: | 1040 | case BO_Sub: |
| 802 | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_Sub"); | 1041 | return trans_create_bin_op(c, block, stmt->getLHS(), |
| 803 | return nullptr; | 1042 | qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeSubWrap : BinOpTypeSub, |
| | 1043 | stmt->getRHS()); |
| 804 | case BO_Shl: | 1044 | case BO_Shl: |
| 805 | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_Shl"); | 1045 | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_Shl"); |
| 806 | return nullptr; | 1046 | return nullptr; |
| ... | @@ -816,29 +1056,22 @@ static AstNode *trans_binary_operator(Context *c, AstNode *block, BinaryOperator | ... | @@ -816,29 +1056,22 @@ static AstNode *trans_binary_operator(Context *c, AstNode *block, BinaryOperator |
| 816 | case BO_GE: | 1056 | case BO_GE: |
| 817 | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeCmpGreaterOrEq, stmt->getRHS()); | 1057 | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeCmpGreaterOrEq, stmt->getRHS()); |
| 818 | case BO_EQ: | 1058 | case BO_EQ: |
| 819 | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_EQ"); | 1059 | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeCmpEq, stmt->getRHS()); |
| 820 | return nullptr; | | |
| 821 | case BO_NE: | 1060 | case BO_NE: |
| 822 | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_NE"); | 1061 | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeCmpNotEq, stmt->getRHS()); |
| 823 | return nullptr; | | |
| 824 | case BO_And: | 1062 | case BO_And: |
| 825 | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_And"); | 1063 | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeBinAnd, stmt->getRHS()); |
| 826 | return nullptr; | | |
| 827 | case BO_Xor: | 1064 | case BO_Xor: |
| 828 | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_Xor"); | 1065 | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeBinXor, stmt->getRHS()); |
| 829 | return nullptr; | | |
| 830 | case BO_Or: | 1066 | case BO_Or: |
| 831 | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_Or"); | 1067 | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeBinOr, stmt->getRHS()); |
| 832 | return nullptr; | | |
| 833 | case BO_LAnd: | 1068 | case BO_LAnd: |
| 834 | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_LAnd"); | 1069 | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeBoolAnd, stmt->getRHS()); |
| 835 | return nullptr; | | |
| 836 | case BO_LOr: | 1070 | case BO_LOr: |
| 837 | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_LOr"); | 1071 | // TODO: int vs bool |
| 838 | return nullptr; | 1072 | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeBoolOr, stmt->getRHS()); |
| 839 | case BO_Assign: | 1073 | case BO_Assign: |
| 840 | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_Assign"); | 1074 | return trans_create_assign(c, result_used, block, stmt->getLHS(), stmt->getRHS()); |
| 841 | return nullptr; | | |
| 842 | case BO_MulAssign: | 1075 | case BO_MulAssign: |
| 843 | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_MulAssign"); | 1076 | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_MulAssign"); |
| 844 | return nullptr; | 1077 | return nullptr; |
| ... | @@ -877,32 +1110,170 @@ static AstNode *trans_binary_operator(Context *c, AstNode *block, BinaryOperator | ... | @@ -877,32 +1110,170 @@ static AstNode *trans_binary_operator(Context *c, AstNode *block, BinaryOperator |
| 877 | zig_unreachable(); | 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 | static AstNode *trans_implicit_cast_expr(Context *c, AstNode *block, ImplicitCastExpr *stmt) { | 1242 | static AstNode *trans_implicit_cast_expr(Context *c, AstNode *block, ImplicitCastExpr *stmt) { |
| 881 | switch (stmt->getCastKind()) { | 1243 | switch (stmt->getCastKind()) { |
| 882 | case CK_LValueToRValue: | 1244 | case CK_LValueToRValue: |
| 883 | return trans_expr(c, block, stmt->getSubExpr()); | 1245 | return trans_expr(c, true, block, stmt->getSubExpr(), TransRValue); |
| 884 | case CK_IntegralCast: | 1246 | case CK_IntegralCast: |
| 885 | { | 1247 | { |
| 886 | AstNode *node = trans_create_node_builtin_fn_call_str(c, "bitCast"); | 1248 | AstNode *target_node = trans_expr(c, true, block, stmt->getSubExpr(), TransRValue); |
| 887 | | 1249 | if (target_node == nullptr) |
| 888 | AstNode *result_type_node = trans_qual_type(c, stmt->getType(), stmt->getExprLoc()); | | |
| 889 | if (result_type_node == nullptr) | | |
| 890 | return nullptr; | 1250 | return nullptr; |
| 891 | | 1251 | return trans_c_cast(c, stmt->getExprLoc(), stmt->getType(), target_node); |
| 892 | AstNode *target_node = trans_expr(c, block, stmt->getSubExpr()); | 1252 | } |
| | 1253 | case CK_FunctionToPointerDecay: |
| | 1254 | case CK_ArrayToPointerDecay: |
| | 1255 | { |
| | 1256 | AstNode *target_node = trans_expr(c, true, block, stmt->getSubExpr(), TransRValue); |
| 893 | if (target_node == nullptr) | 1257 | if (target_node == nullptr) |
| 894 | return nullptr; | 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 | node->data.fn_call_expr.params.append(target_node); | 1271 | node->data.fn_call_expr.params.append(target_node); |
| 898 | return node; | 1272 | return node; |
| 899 | } | 1273 | } |
| 900 | case CK_Dependent: | 1274 | case CK_Dependent: |
| 901 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_Dependent"); | 1275 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_Dependent"); |
| 902 | return nullptr; | 1276 | return nullptr; |
| 903 | case CK_BitCast: | | |
| 904 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_BitCast"); | | |
| 905 | return nullptr; | | |
| 906 | case CK_LValueBitCast: | 1277 | case CK_LValueBitCast: |
| 907 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_LValueBitCast"); | 1278 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_LValueBitCast"); |
| 908 | return nullptr; | 1279 | return nullptr; |
| ... | @@ -924,12 +1295,6 @@ static AstNode *trans_implicit_cast_expr(Context *c, AstNode *block, ImplicitCas | ... | @@ -924,12 +1295,6 @@ static AstNode *trans_implicit_cast_expr(Context *c, AstNode *block, ImplicitCas |
| 924 | case CK_ToUnion: | 1295 | case CK_ToUnion: |
| 925 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ToUnion"); | 1296 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ToUnion"); |
| 926 | return nullptr; | 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 | case CK_NullToPointer: | 1298 | case CK_NullToPointer: |
| 934 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_NullToPointer"); | 1299 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_NullToPointer"); |
| 935 | return nullptr; | 1300 | return nullptr; |
| ... | @@ -1069,17 +1434,44 @@ static AstNode *trans_implicit_cast_expr(Context *c, AstNode *block, ImplicitCas | ... | @@ -1069,17 +1434,44 @@ static AstNode *trans_implicit_cast_expr(Context *c, AstNode *block, ImplicitCas |
| 1069 | zig_unreachable(); | 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 | ValueDecl *value_decl = stmt->getDecl(); | 1438 | ValueDecl *value_decl = stmt->getDecl(); |
| 1074 | const char *name = decl_name(value_decl); | 1439 | Buf *symbol_name = buf_create_from_str(decl_name(value_decl)); |
| 1075 | return trans_create_node_symbol_str(c, name); | 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 | switch (stmt->getOpcode()) { | 1447 | switch (stmt->getOpcode()) { |
| 1080 | case UO_PostInc: | 1448 | case UO_PostInc: { |
| 1081 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_PostInc"); | 1449 | Expr *op_expr = stmt->getSubExpr(); |
| 1082 | return nullptr; | 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 | case UO_PostDec: | 1475 | case UO_PostDec: |
| 1084 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_PostDec"); | 1476 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_PostDec"); |
| 1085 | return nullptr; | 1477 | return nullptr; |
| ... | @@ -1101,11 +1493,11 @@ static AstNode *trans_unary_operator(Context *c, AstNode *block, UnaryOperator * | ... | @@ -1101,11 +1493,11 @@ static AstNode *trans_unary_operator(Context *c, AstNode *block, UnaryOperator * |
| 1101 | case UO_Minus: | 1493 | case UO_Minus: |
| 1102 | { | 1494 | { |
| 1103 | Expr *op_expr = stmt->getSubExpr(); | 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 | AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr); | 1497 | AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr); |
| 1106 | node->data.prefix_op_expr.prefix_op = PrefixOpNegation; | 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 | if (node->data.prefix_op_expr.primary_expr == nullptr) | 1501 | if (node->data.prefix_op_expr.primary_expr == nullptr) |
| 1110 | return nullptr; | 1502 | return nullptr; |
| 1111 | | 1503 | |
| ... | @@ -1115,7 +1507,7 @@ static AstNode *trans_unary_operator(Context *c, AstNode *block, UnaryOperator * | ... | @@ -1115,7 +1507,7 @@ static AstNode *trans_unary_operator(Context *c, AstNode *block, UnaryOperator * |
| 1115 | AstNode *node = trans_create_node(c, NodeTypeBinOpExpr); | 1507 | AstNode *node = trans_create_node(c, NodeTypeBinOpExpr); |
| 1116 | node->data.bin_op_expr.op1 = trans_create_node_unsigned(c, 0); | 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 | if (node->data.bin_op_expr.op2 == nullptr) | 1511 | if (node->data.bin_op_expr.op2 == nullptr) |
| 1120 | return nullptr; | 1512 | return nullptr; |
| 1121 | | 1513 | |
| ... | @@ -1157,7 +1549,7 @@ static AstNode *trans_local_declaration(Context *c, AstNode *block, DeclStmt *st | ... | @@ -1157,7 +1549,7 @@ static AstNode *trans_local_declaration(Context *c, AstNode *block, DeclStmt *st |
| 1157 | QualType qual_type = var_decl->getTypeSourceInfo()->getType(); | 1549 | QualType qual_type = var_decl->getTypeSourceInfo()->getType(); |
| 1158 | AstNode *init_node = nullptr; | 1550 | AstNode *init_node = nullptr; |
| 1159 | if (var_decl->hasInit()) { | 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 | if (init_node == nullptr) | 1553 | if (init_node == nullptr) |
| 1162 | return nullptr; | 1554 | return nullptr; |
| 1163 | | 1555 | |
| ... | @@ -1166,8 +1558,10 @@ static AstNode *trans_local_declaration(Context *c, AstNode *block, DeclStmt *st | ... | @@ -1166,8 +1558,10 @@ static AstNode *trans_local_declaration(Context *c, AstNode *block, DeclStmt *st |
| 1166 | if (type_node == nullptr) | 1558 | if (type_node == nullptr) |
| 1167 | return nullptr; | 1559 | return nullptr; |
| 1168 | | 1560 | |
| 1169 | AstNode *node = trans_create_node_var_decl(c, qual_type.isConstQualified(), | 1561 | Buf *symbol_name = buf_create_from_str(decl_name(var_decl)); |
| 1170 | buf_create_from_str(decl_name(var_decl)), type_node, init_node); | 1562 | |
| | 1563 | AstNode *node = trans_create_node_var_decl_local(c, qual_type.isConstQualified(), |
| | 1564 | symbol_name, type_node, init_node); |
| 1171 | block->data.block.statements.append(node); | 1565 | block->data.block.statements.append(node); |
| 1172 | continue; | 1566 | continue; |
| 1173 | } | 1567 | } |
| ... | @@ -1398,18 +1792,112 @@ static AstNode *trans_local_declaration(Context *c, AstNode *block, DeclStmt *st | ... | @@ -1398,18 +1792,112 @@ static AstNode *trans_local_declaration(Context *c, AstNode *block, DeclStmt *st |
| 1398 | static AstNode *trans_while_loop(Context *c, AstNode *block, WhileStmt *stmt) { | 1792 | static AstNode *trans_while_loop(Context *c, AstNode *block, WhileStmt *stmt) { |
| 1399 | AstNode *while_node = trans_create_node(c, NodeTypeWhileExpr); | 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 | if (while_node->data.while_expr.condition == nullptr) | 1796 | if (while_node->data.while_expr.condition == nullptr) |
| 1403 | return nullptr; | 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 | if (while_node->data.while_expr.body == nullptr) | 1800 | if (while_node->data.while_expr.body == nullptr) |
| 1407 | return nullptr; | 1801 | return nullptr; |
| 1408 | | 1802 | |
| 1409 | return while_node; | 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 | Stmt::StmtClass sc = stmt->getStmtClass(); | 1901 | Stmt::StmtClass sc = stmt->getStmtClass(); |
| 1414 | switch (sc) { | 1902 | switch (sc) { |
| 1415 | case Stmt::ReturnStmtClass: | 1903 | case Stmt::ReturnStmtClass: |
| ... | @@ -1419,19 +1907,35 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) { | ... | @@ -1419,19 +1907,35 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) { |
| 1419 | case Stmt::IntegerLiteralClass: | 1907 | case Stmt::IntegerLiteralClass: |
| 1420 | return trans_integer_literal(c, (IntegerLiteral *)stmt); | 1908 | return trans_integer_literal(c, (IntegerLiteral *)stmt); |
| 1421 | case Stmt::ConditionalOperatorClass: | 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 | case Stmt::BinaryOperatorClass: | 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 | case Stmt::ImplicitCastExprClass: | 1915 | case Stmt::ImplicitCastExprClass: |
| 1426 | return trans_implicit_cast_expr(c, block, (ImplicitCastExpr *)stmt); | 1916 | return trans_implicit_cast_expr(c, block, (ImplicitCastExpr *)stmt); |
| 1427 | case Stmt::DeclRefExprClass: | 1917 | case Stmt::DeclRefExprClass: |
| 1428 | return trans_decl_ref_expr(c, (DeclRefExpr *)stmt); | 1918 | return trans_decl_ref_expr(c, (DeclRefExpr *)stmt, lrvalue); |
| 1429 | case Stmt::UnaryOperatorClass: | 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 | case Stmt::DeclStmtClass: | 1921 | case Stmt::DeclStmtClass: |
| 1432 | return trans_local_declaration(c, block, (DeclStmt *)stmt); | 1922 | return trans_local_declaration(c, block, (DeclStmt *)stmt); |
| 1433 | case Stmt::WhileStmtClass: | 1923 | case Stmt::WhileStmtClass: |
| 1434 | return trans_while_loop(c, block, (WhileStmt *)stmt); | 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 | case Stmt::CaseStmtClass: | 1939 | case Stmt::CaseStmtClass: |
| 1436 | emit_warning(c, stmt->getLocStart(), "TODO handle C CaseStmtClass"); | 1940 | emit_warning(c, stmt->getLocStart(), "TODO handle C CaseStmtClass"); |
| 1437 | return nullptr; | 1941 | return nullptr; |
| ... | @@ -1492,9 +1996,6 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) { | ... | @@ -1492,9 +1996,6 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) { |
| 1492 | case Stmt::ArrayInitLoopExprClass: | 1996 | case Stmt::ArrayInitLoopExprClass: |
| 1493 | emit_warning(c, stmt->getLocStart(), "TODO handle C ArrayInitLoopExprClass"); | 1997 | emit_warning(c, stmt->getLocStart(), "TODO handle C ArrayInitLoopExprClass"); |
| 1494 | return nullptr; | 1998 | return nullptr; |
| 1495 | case Stmt::ArraySubscriptExprClass: | | |
| 1496 | emit_warning(c, stmt->getLocStart(), "TODO handle C ArraySubscriptExprClass"); | | |
| 1497 | return nullptr; | | |
| 1498 | case Stmt::ArrayTypeTraitExprClass: | 1999 | case Stmt::ArrayTypeTraitExprClass: |
| 1499 | emit_warning(c, stmt->getLocStart(), "TODO handle C ArrayTypeTraitExprClass"); | 2000 | emit_warning(c, stmt->getLocStart(), "TODO handle C ArrayTypeTraitExprClass"); |
| 1500 | return nullptr; | 2001 | return nullptr; |
| ... | @@ -1504,9 +2005,6 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) { | ... | @@ -1504,9 +2005,6 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) { |
| 1504 | case Stmt::AtomicExprClass: | 2005 | case Stmt::AtomicExprClass: |
| 1505 | emit_warning(c, stmt->getLocStart(), "TODO handle C AtomicExprClass"); | 2006 | emit_warning(c, stmt->getLocStart(), "TODO handle C AtomicExprClass"); |
| 1506 | return nullptr; | 2007 | return nullptr; |
| 1507 | case Stmt::CompoundAssignOperatorClass: | | |
| 1508 | emit_warning(c, stmt->getLocStart(), "TODO handle C CompoundAssignOperatorClass"); | | |
| 1509 | return nullptr; | | |
| 1510 | case Stmt::BlockExprClass: | 2008 | case Stmt::BlockExprClass: |
| 1511 | emit_warning(c, stmt->getLocStart(), "TODO handle C BlockExprClass"); | 2009 | emit_warning(c, stmt->getLocStart(), "TODO handle C BlockExprClass"); |
| 1512 | return nullptr; | 2010 | return nullptr; |
| ... | @@ -1573,13 +2071,11 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) { | ... | @@ -1573,13 +2071,11 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) { |
| 1573 | case Stmt::CXXUuidofExprClass: | 2071 | case Stmt::CXXUuidofExprClass: |
| 1574 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXUuidofExprClass"); | 2072 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXUuidofExprClass"); |
| 1575 | return nullptr; | 2073 | return nullptr; |
| 1576 | case Stmt::CallExprClass: | | |
| 1577 | emit_warning(c, stmt->getLocStart(), "TODO handle C CallExprClass"); | | |
| 1578 | return nullptr; | | |
| 1579 | case Stmt::CUDAKernelCallExprClass: | 2074 | case Stmt::CUDAKernelCallExprClass: |
| 1580 | emit_warning(c, stmt->getLocStart(), "TODO handle C CUDAKernelCallExprClass"); | 2075 | emit_warning(c, stmt->getLocStart(), "TODO handle C CUDAKernelCallExprClass"); |
| 1581 | return nullptr; | 2076 | return nullptr; |
| 1582 | case Stmt::CXXMemberCallExprClass: | 2077 | case Stmt::CXXMemberCallExprClass: |
| | 2078 | (void)result_used; |
| 1583 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXMemberCallExprClass"); | 2079 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXMemberCallExprClass"); |
| 1584 | return nullptr; | 2080 | return nullptr; |
| 1585 | case Stmt::CXXOperatorCallExprClass: | 2081 | case Stmt::CXXOperatorCallExprClass: |
| ... | @@ -1588,9 +2084,6 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) { | ... | @@ -1588,9 +2084,6 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) { |
| 1588 | case Stmt::UserDefinedLiteralClass: | 2084 | case Stmt::UserDefinedLiteralClass: |
| 1589 | emit_warning(c, stmt->getLocStart(), "TODO handle C UserDefinedLiteralClass"); | 2085 | emit_warning(c, stmt->getLocStart(), "TODO handle C UserDefinedLiteralClass"); |
| 1590 | return nullptr; | 2086 | return nullptr; |
| 1591 | case Stmt::CStyleCastExprClass: | | |
| 1592 | emit_warning(c, stmt->getLocStart(), "TODO handle C CStyleCastExprClass"); | | |
| 1593 | return nullptr; | | |
| 1594 | case Stmt::CXXFunctionalCastExprClass: | 2087 | case Stmt::CXXFunctionalCastExprClass: |
| 1595 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXFunctionalCastExprClass"); | 2088 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXFunctionalCastExprClass"); |
| 1596 | return nullptr; | 2089 | return nullptr; |
| ... | @@ -1681,9 +2174,6 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) { | ... | @@ -1681,9 +2174,6 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) { |
| 1681 | case Stmt::MaterializeTemporaryExprClass: | 2174 | case Stmt::MaterializeTemporaryExprClass: |
| 1682 | emit_warning(c, stmt->getLocStart(), "TODO handle C MaterializeTemporaryExprClass"); | 2175 | emit_warning(c, stmt->getLocStart(), "TODO handle C MaterializeTemporaryExprClass"); |
| 1683 | return nullptr; | 2176 | return nullptr; |
| 1684 | case Stmt::MemberExprClass: | | |
| 1685 | emit_warning(c, stmt->getLocStart(), "TODO handle C MemberExprClass"); | | |
| 1686 | return nullptr; | | |
| 1687 | case Stmt::NoInitExprClass: | 2177 | case Stmt::NoInitExprClass: |
| 1688 | emit_warning(c, stmt->getLocStart(), "TODO handle C NoInitExprClass"); | 2178 | emit_warning(c, stmt->getLocStart(), "TODO handle C NoInitExprClass"); |
| 1689 | return nullptr; | 2179 | return nullptr; |
| ... | @@ -1751,8 +2241,7 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) { | ... | @@ -1751,8 +2241,7 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) { |
| 1751 | emit_warning(c, stmt->getLocStart(), "TODO handle C PackExpansionExprClass"); | 2241 | emit_warning(c, stmt->getLocStart(), "TODO handle C PackExpansionExprClass"); |
| 1752 | return nullptr; | 2242 | return nullptr; |
| 1753 | case Stmt::ParenExprClass: | 2243 | case Stmt::ParenExprClass: |
| 1754 | emit_warning(c, stmt->getLocStart(), "TODO handle C ParenExprClass"); | 2244 | return trans_expr(c, result_used, block, ((ParenExpr*)stmt)->getSubExpr(), lrvalue); |
| 1755 | return nullptr; | | |
| 1756 | case Stmt::ParenListExprClass: | 2245 | case Stmt::ParenListExprClass: |
| 1757 | emit_warning(c, stmt->getLocStart(), "TODO handle C ParenListExprClass"); | 2246 | emit_warning(c, stmt->getLocStart(), "TODO handle C ParenListExprClass"); |
| 1758 | return nullptr; | 2247 | return nullptr; |
| ... | @@ -1786,9 +2275,6 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) { | ... | @@ -1786,9 +2275,6 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) { |
| 1786 | case Stmt::TypoExprClass: | 2275 | case Stmt::TypoExprClass: |
| 1787 | emit_warning(c, stmt->getLocStart(), "TODO handle C TypoExprClass"); | 2276 | emit_warning(c, stmt->getLocStart(), "TODO handle C TypoExprClass"); |
| 1788 | return nullptr; | 2277 | return nullptr; |
| 1789 | case Stmt::UnaryExprOrTypeTraitExprClass: | | |
| 1790 | emit_warning(c, stmt->getLocStart(), "TODO handle C UnaryExprOrTypeTraitExprClass"); | | |
| 1791 | return nullptr; | | |
| 1792 | case Stmt::VAArgExprClass: | 2278 | case Stmt::VAArgExprClass: |
| 1793 | emit_warning(c, stmt->getLocStart(), "TODO handle C VAArgExprClass"); | 2279 | emit_warning(c, stmt->getLocStart(), "TODO handle C VAArgExprClass"); |
| 1794 | return nullptr; | 2280 | return nullptr; |
| ... | @@ -1798,9 +2284,6 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) { | ... | @@ -1798,9 +2284,6 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) { |
| 1798 | case Stmt::GotoStmtClass: | 2284 | case Stmt::GotoStmtClass: |
| 1799 | emit_warning(c, stmt->getLocStart(), "TODO handle C GotoStmtClass"); | 2285 | emit_warning(c, stmt->getLocStart(), "TODO handle C GotoStmtClass"); |
| 1800 | return nullptr; | 2286 | return nullptr; |
| 1801 | case Stmt::IfStmtClass: | | |
| 1802 | emit_warning(c, stmt->getLocStart(), "TODO handle C IfStmtClass"); | | |
| 1803 | return nullptr; | | |
| 1804 | case Stmt::IndirectGotoStmtClass: | 2287 | case Stmt::IndirectGotoStmtClass: |
| 1805 | emit_warning(c, stmt->getLocStart(), "TODO handle C IndirectGotoStmtClass"); | 2288 | emit_warning(c, stmt->getLocStart(), "TODO handle C IndirectGotoStmtClass"); |
| 1806 | return nullptr; | 2289 | return nullptr; |
| ... | @@ -1810,9 +2293,6 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) { | ... | @@ -1810,9 +2293,6 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) { |
| 1810 | case Stmt::MSDependentExistsStmtClass: | 2293 | case Stmt::MSDependentExistsStmtClass: |
| 1811 | emit_warning(c, stmt->getLocStart(), "TODO handle C MSDependentExistsStmtClass"); | 2294 | emit_warning(c, stmt->getLocStart(), "TODO handle C MSDependentExistsStmtClass"); |
| 1812 | return nullptr; | 2295 | return nullptr; |
| 1813 | case Stmt::NullStmtClass: | | |
| 1814 | emit_warning(c, stmt->getLocStart(), "TODO handle C NullStmtClass"); | | |
| 1815 | return nullptr; | | |
| 1816 | case Stmt::OMPAtomicDirectiveClass: | 2296 | case Stmt::OMPAtomicDirectiveClass: |
| 1817 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPAtomicDirectiveClass"); | 2297 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPAtomicDirectiveClass"); |
| 1818 | return nullptr; | 2298 | return nullptr; |
| ... | @@ -2025,36 +2505,65 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { | ... | @@ -2025,36 +2505,65 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { |
| 2025 | AstNode *param_node = proto_node->data.fn_proto.params.at(i); | 2505 | AstNode *param_node = proto_node->data.fn_proto.params.at(i); |
| 2026 | const ParmVarDecl *param = fn_decl->getParamDecl(i); | 2506 | const ParmVarDecl *param = fn_decl->getParamDecl(i); |
| 2027 | const char *name = decl_name(param); | 2507 | const char *name = decl_name(param); |
| 2028 | if (strlen(name) == 0) { | 2508 | Buf *proto_param_name; |
| 2029 | Buf *proto_param_name = param_node->data.param_decl.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 | if (proto_param_name == nullptr) { | 2513 | if (proto_param_name == nullptr) { |
| 2031 | param_node->data.param_decl.name = buf_sprintf("arg%" ZIG_PRI_usize "", i); | 2514 | proto_param_name = buf_sprintf("arg%" ZIG_PRI_usize "", i); |
| 2032 | } else { | | |
| 2033 | param_node->data.param_decl.name = proto_param_name; | | |
| 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()) { | 2526 | // actual function definition with body |
| 2041 | Stmt *body = fn_decl->getBody(); | 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); | 2536 | // it worked |
| 2044 | fn_def_node->data.fn_def.fn_proto = proto_node; | 2537 | |
| 2045 | fn_def_node->data.fn_def.body = trans_stmt(c, nullptr, body); | 2538 | assert(actual_body_node->type == NodeTypeBlock); |
| 2046 | assert(fn_def_node->data.fn_def.body != skip_add_to_block_node); | 2539 | AstNode *body_node_with_param_inits = trans_create_node(c, NodeTypeBlock); |
| 2047 | if (fn_def_node->data.fn_def.body == nullptr) { | 2540 | |
| 2048 | emit_warning(c, fn_decl->getLocation(), "unable to translate function"); | 2541 | for (size_t i = 0; i < proto_node->data.fn_proto.params.length; i += 1) { |
| 2049 | return; | 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; | 2557 | for (size_t i = 0; i < actual_body_node->data.block.statements.length; i += 1) { |
| 2053 | c->root->data.root.top_level_decls.append(fn_def_node); | 2558 | body_node_with_param_inits->data.block.statements.append(actual_body_node->data.block.statements.at(i)); |
| 2054 | return; | | |
| 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 | static AstNode *resolve_typdef_as_builtin(Context *c, const TypedefNameDecl *typedef_decl, const char *primitive_name) { | 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,9 +2699,14 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) { |
| 2190 | | 2699 | |
| 2191 | // in C each enum value is in the global namespace. so we put them there too. | 2700 | // in C each enum value is in the global namespace. so we put them there too. |
| 2192 | // at this point we can rely on the enum emitting successfully | 2701 | // at this point we can rely on the enum emitting successfully |
| 2193 | AstNode *field_access_node = trans_create_node_field_access(c, | 2702 | if (is_anonymous) { |
| 2194 | trans_create_node_symbol(c, full_type_name), field_name); | 2703 | AstNode *lit_node = trans_create_node_unsigned(c, i); |
| 2195 | add_global_var(c, enum_val_name, field_access_node); | 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 | if (is_anonymous) { | 2712 | if (is_anonymous) { |
| ... | @@ -2376,7 +2890,7 @@ static void visit_var_decl(Context *c, const VarDecl *var_decl) { | ... | @@ -2376,7 +2890,7 @@ static void visit_var_decl(Context *c, const VarDecl *var_decl) { |
| 2376 | init_node = trans_create_node_apint(c, ap_value->getInt()); | 2890 | init_node = trans_create_node_apint(c, ap_value->getInt()); |
| 2377 | break; | 2891 | break; |
| 2378 | case APValue::Uninitialized: | 2892 | case APValue::Uninitialized: |
| 2379 | init_node = trans_create_node_symbol_str(c, "undefined"); | 2893 | init_node = trans_create_node(c, NodeTypeUndefinedLiteral); |
| 2380 | break; | 2894 | break; |
| 2381 | case APValue::Float: | 2895 | case APValue::Float: |
| 2382 | case APValue::ComplexInt: | 2896 | case APValue::ComplexInt: |
| ... | @@ -2393,16 +2907,16 @@ static void visit_var_decl(Context *c, const VarDecl *var_decl) { | ... | @@ -2393,16 +2907,16 @@ static void visit_var_decl(Context *c, const VarDecl *var_decl) { |
| 2393 | return; | 2907 | return; |
| 2394 | } | 2908 | } |
| 2395 | } else { | 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 | c->root->data.root.top_level_decls.append(var_node); | 2914 | c->root->data.root.top_level_decls.append(var_node); |
| 2401 | return; | 2915 | return; |
| 2402 | } | 2916 | } |
| 2403 | | 2917 | |
| 2404 | if (is_extern) { | 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 | var_node->data.variable_declaration.is_extern = true; | 2920 | var_node->data.variable_declaration.is_extern = true; |
| 2407 | c->root->data.root.top_level_decls.append(var_node); | 2921 | c->root->data.root.top_level_decls.append(var_node); |
| 2408 | return; | 2922 | return; |
| ... | @@ -2663,6 +3177,7 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const ch | ... | @@ -2663,6 +3177,7 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const ch |
| 2663 | c->visib_mod = VisibModPub; | 3177 | c->visib_mod = VisibModPub; |
| 2664 | c->decl_table.init(8); | 3178 | c->decl_table.init(8); |
| 2665 | c->macro_table.init(8); | 3179 | c->macro_table.init(8); |
| | 3180 | c->ptr_params.init(8); |
| 2666 | c->codegen = codegen; | 3181 | c->codegen = codegen; |
| 2667 | c->source_node = source_node; | 3182 | c->source_node = source_node; |
| 2668 | | 3183 | |