authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-09-21 02:56:06-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-09-21 02:56:06-04:00
logc2f3dc94eba85a32f3b7ab5857b33636a0a2e4df
treebb809f8eb6a1d7fb709607dcadce511b2a58dd8f
parentc4a54377e3f07bbd2f9c54c1962c7941792c2c1f
parentee42caee0e6a24aa252845a72733007ed384d2bf

Merge branch 'c-to-zig'


8 files changed, 958 insertions(+), 147 deletions(-)

src/analyze.cpp-4
...@@ -163,10 +163,6 @@ static TypeTableEntry *new_container_type_entry(TypeTableEntryId id, AstNode *so...@@ -163,10 +163,6 @@ static TypeTableEntry *new_container_type_entry(TypeTableEntryId id, AstNode *so
163 return entry;163 return entry;
164}164}
165165
166static uint8_t log2_u64(uint64_t x) {
167 return (63 - clzll(x));
168}
169
170static uint8_t bits_needed_for_unsigned(uint64_t x) {166static uint8_t bits_needed_for_unsigned(uint64_t x) {
171 if (x == 0) {167 if (x == 0) {
172 return 0;168 return 0;
src/ast_render.cpp+4-2
...@@ -14,8 +14,8 @@...@@ -14,8 +14,8 @@
14static const char *bin_op_str(BinOpType bin_op) {14static const char *bin_op_str(BinOpType bin_op) {
15 switch (bin_op) {15 switch (bin_op) {
16 case BinOpTypeInvalid: return "(invalid)";16 case BinOpTypeInvalid: return "(invalid)";
17 case BinOpTypeBoolOr: return "||";17 case BinOpTypeBoolOr: return "or";
18 case BinOpTypeBoolAnd: return "&&";18 case BinOpTypeBoolAnd: return "and";
19 case BinOpTypeCmpEq: return "==";19 case BinOpTypeCmpEq: return "==";
20 case BinOpTypeCmpNotEq: return "!=";20 case BinOpTypeCmpNotEq: return "!=";
21 case BinOpTypeCmpLessThan: return "<";21 case BinOpTypeCmpLessThan: return "<";
...@@ -580,10 +580,12 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {...@@ -580,10 +580,12 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
580 break;580 break;
581 case NodeTypePrefixOpExpr:581 case NodeTypePrefixOpExpr:
582 {582 {
583 if (!grouped) fprintf(ar->f, "(");
583 PrefixOp op = node->data.prefix_op_expr.prefix_op;584 PrefixOp op = node->data.prefix_op_expr.prefix_op;
584 fprintf(ar->f, "%s", prefix_op_str(op));585 fprintf(ar->f, "%s", prefix_op_str(op));
585586
586 render_node_ungrouped(ar, node->data.prefix_op_expr.primary_expr);587 render_node_ungrouped(ar, node->data.prefix_op_expr.primary_expr);
588 if (!grouped) fprintf(ar->f, ")");
587 break;589 break;
588 }590 }
589 case NodeTypeAddrOfExpr:591 case NodeTypeAddrOfExpr:
src/codegen.cpp+1-1
...@@ -5037,7 +5037,7 @@ void codegen_parsec(CodeGen *g, Buf *full_path) {...@@ -5037,7 +5037,7 @@ void codegen_parsec(CodeGen *g, Buf *full_path) {
5037 ZigList<ErrorMsg *> errors = {0};5037 ZigList<ErrorMsg *> errors = {0};
5038 int err = parse_h_file(import, &errors, buf_ptr(full_path), g, nullptr);5038 int err = parse_h_file(import, &errors, buf_ptr(full_path), g, nullptr);
5039 if (err) {5039 if (err) {
5040 fprintf(stderr, "unable to parse .h file: %s\n", err_str(err));5040 fprintf(stderr, "unable to parse C file: %s\n", err_str(err));
5041 exit(1);5041 exit(1);
5042 }5042 }
50435043
src/ir.cpp+1-1
...@@ -13459,7 +13459,7 @@ static TypeTableEntry *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruc...@@ -13459,7 +13459,7 @@ static TypeTableEntry *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruc
1345913459
13460 int err;13460 int err;
13461 if ((err = parse_h_buf(child_import, &errors, &cimport_scope->buf, ira->codegen, node))) {13461 if ((err = parse_h_buf(child_import, &errors, &cimport_scope->buf, ira->codegen, node))) {
13462 zig_panic("unable to parse h file: %s\n", err_str(err));13462 zig_panic("unable to parse C file: %s\n", err_str(err));
13463 }13463 }
1346413464
13465 if (errors.length > 0) {13465 if (errors.length > 0) {
src/parsec.cpp+651-136
...@@ -49,6 +49,8 @@ struct Context {...@@ -49,6 +49,8 @@ struct Context {
4949
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};
5355
54static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl);56static 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}
128130
131static 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
129static AstNode *trans_create_node_field_access(Context *c, AstNode *container, Buf *field_name) {138static 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}
135147
148static 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
136static AstNode *trans_create_node_prefix_op(Context *c, PrefixOp op, AstNode *child_node) {152static 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}
142158
159static 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
167static 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
143static AstNode *trans_create_node_addr_of(Context *c, bool is_const, bool is_volatile, AstNode *child_node) {175static 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}
157189
190static 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
158static AstNode *trans_create_node_unsigned_negative(Context *c, uint64_t x, bool is_negative) {197static 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}
190229
191static AstNode *trans_create_node_var_decl(Context *c, bool is_const, Buf *var_name, AstNode *type_node,230static 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}
202241
242static 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
248static 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
203254
204static AstNode *trans_create_node_inline_fn(Context *c, Buf *fn_name, Buf *var_name, AstNode *src_proto_node) {255static 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}
242293
294static AstNode *trans_create_node_unwrap_null(Context *c, AstNode *child) {
295 return trans_create_node_prefix_op(c, PrefixOpUnwrapMaybe, child);
296}
297
243static AstNode *get_global(Context *c, Buf *name) {298static 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) {
268static AstNode *add_global_var(Context *c, Buf *var_name, AstNode *value_node) {323static 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)
286341
287}342}
288343
344static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc);
345
289static bool is_c_void_type(AstNode *node) {346static 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}
292349
350static 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
357static 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
401static 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
293static bool qual_type_child_is_fn_proto(const QualType &qt) {434static 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}
305446
447static 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
306static bool c_is_signed_integer(Context *c, QualType qt) {456static 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}
324474
325static bool c_is_unsigned_integer(Context *c, QualType qt) {475static 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}
362512
363static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt);513static bool qual_type_has_wrapping_overflow(Context *c, QualType qt) {
364static 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
523enum TransLRValue {
524 TransLValue,
525 TransRValue,
526};
527
528static AstNode *trans_stmt(Context *c, bool result_used, AstNode *block, Stmt *stmt, TransLRValue lrval);
365static AstNode *const skip_add_to_block_node = (AstNode *) 0x2;529static AstNode *const skip_add_to_block_node = (AstNode *) 0x2;
366530
367static AstNode *trans_expr(Context *c, AstNode *block, Expr *expr) {531static 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}
370534
371static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &source_loc) {535static 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
709static AstNode *trans_compound_stmt(Context *c, AstNode *parent, CompoundStmt *stmt) {873static 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}
743907
744static AstNode *trans_conditional_operator(Context *c, AstNode *block, ConditionalOperator *stmt) {908static 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);
746910
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();
750914
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;
754918
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;
758922
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;
762926
763 return node;927 return maybe_suppress_result(c, result_used, node);
764}928}
765929
766static AstNode *trans_create_bin_op(Context *c, AstNode *block, Expr *lhs, BinOpType bin_op, Expr *rhs) {930static 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;
769933
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;
773937
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;
777941
778 return node;942 return node;
779}943}
780944
781static AstNode *trans_binary_operator(Context *c, AstNode *block, BinaryOperator *stmt) {945static 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
994static 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}
8791112
1113static 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
880static AstNode *trans_implicit_cast_expr(Context *c, AstNode *block, ImplicitCastExpr *stmt) {1242static 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);
8871249 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;
8911251 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());
8951268
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}
10711436
1072static AstNode *trans_decl_ref_expr(Context *c, DeclRefExpr *stmt) {1437static 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}
10771445
1078static AstNode *trans_unary_operator(Context *c, AstNode *block, UnaryOperator *stmt) {1446static 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;
11071499
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;
11111503
...@@ -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);
11171509
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;
11211513
...@@ -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;
11631555
...@@ -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;
11681560
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
1398static AstNode *trans_while_loop(Context *c, AstNode *block, WhileStmt *stmt) {1792static 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);
14001794
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;
14041798
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;
14081802
1409 return while_node;1803 return while_node;
1410}1804}
14111805
1412static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) {1806static 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
1830static 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
1849static 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
1864static 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
1880static 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
1890static 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
1900static 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 }
20392525
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 }
20422535
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 }
20512556
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 }
20562560
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}
20592568
2060static AstNode *resolve_typdef_as_builtin(Context *c, const TypedefNameDecl *typedef_decl, const char *primitive_name) {2569static 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) {
21902699
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 successfully2701 // 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 }
21972711
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 }
23982912
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 }
24032917
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;
26683183
src/util.hpp+4
...@@ -147,4 +147,8 @@ bool uint64_eq(uint64_t a, uint64_t b);...@@ -147,4 +147,8 @@ bool uint64_eq(uint64_t a, uint64_t b);
147uint32_t ptr_hash(const void *ptr);147uint32_t ptr_hash(const void *ptr);
148bool ptr_eq(const void *a, const void *b);148bool ptr_eq(const void *a, const void *b);
149149
150static inline uint8_t log2_u64(uint64_t x) {
151 return (63 - clzll(x));
152}
153
150#endif154#endif
test/parsec.zig+295-1
...@@ -98,7 +98,7 @@ pub fn addCases(cases: &tests.ParseCContext) {...@@ -98,7 +98,7 @@ pub fn addCases(cases: &tests.ParseCContext) {
98 ,98 ,
99 \\pub const BarB = enum_Bar.B;99 \\pub const BarB = enum_Bar.B;
100 ,100 ,
101 \\pub extern fn func(a: ?&struct_Foo, b: ?&?&enum_Bar);101 \\pub extern fn func(a: ?&struct_Foo, b: ?&(?&enum_Bar));
102 ,102 ,
103 \\pub const Foo = struct_Foo;103 \\pub const Foo = struct_Foo;
104 ,104 ,
...@@ -314,4 +314,298 @@ pub fn addCases(cases: &tests.ParseCContext) {...@@ -314,4 +314,298 @@ pub fn addCases(cases: &tests.ParseCContext) {
314 ,314 ,
315 \\pub const LUA_GLOBALSINDEX = -10002;315 \\pub const LUA_GLOBALSINDEX = -10002;
316 );316 );
317
318 cases.add("post increment",
319 \\unsigned foo1(unsigned a) {
320 \\ a++;
321 \\ return a;
322 \\}
323 \\int foo2(int a) {
324 \\ a++;
325 \\ return a;
326 \\}
327 ,
328 \\export fn foo1(_arg_a: c_uint) -> c_uint {
329 \\ var a = _arg_a;
330 \\ a +%= 1;
331 \\ return a;
332 \\}
333 \\export fn foo2(_arg_a: c_int) -> c_int {
334 \\ var a = _arg_a;
335 \\ a += 1;
336 \\ return a;
337 \\}
338 );
339
340 cases.add("shift right assign",
341 \\int log2(unsigned a) {
342 \\ int i = 0;
343 \\ while (a > 0) {
344 \\ a >>= 1;
345 \\ }
346 \\ return i;
347 \\}
348 ,
349 \\export fn log2(_arg_a: c_uint) -> c_int {
350 \\ var a = _arg_a;
351 \\ var i: c_int = 0;
352 \\ while (a > c_uint(0)) {
353 \\ a >>= @import("std").math.Log2Int(c_uint)(1);
354 \\ };
355 \\ return i;
356 \\}
357 );
358
359 cases.add("if statement",
360 \\int max(int a, int b) {
361 \\ if (a < b)
362 \\ return b;
363 \\
364 \\ if (a < b)
365 \\ return b;
366 \\ else
367 \\ return a;
368 \\}
369 ,
370 \\export fn max(a: c_int, b: c_int) -> c_int {
371 \\ if (a < b) return b;
372 \\ if (a < b) return b else return a;
373 \\}
374 );
375
376 cases.add("==, !=",
377 \\int max(int a, int b) {
378 \\ if (a == b)
379 \\ return a;
380 \\ if (a != b)
381 \\ return b;
382 \\ return a;
383 \\}
384 ,
385 \\export fn max(a: c_int, b: c_int) -> c_int {
386 \\ if (a == b) return a;
387 \\ if (a != b) return b;
388 \\ return a;
389 \\}
390 );
391
392 cases.add("add, sub, mul, div, rem",
393 \\int s(int a, int b) {
394 \\ int c;
395 \\ c = a + b;
396 \\ c = a - b;
397 \\ c = a * b;
398 \\ c = a / b;
399 \\ c = a % b;
400 \\}
401 \\unsigned u(unsigned a, unsigned b) {
402 \\ unsigned c;
403 \\ c = a + b;
404 \\ c = a - b;
405 \\ c = a * b;
406 \\ c = a / b;
407 \\ c = a % b;
408 \\}
409 ,
410 \\export fn s(a: c_int, b: c_int) -> c_int {
411 \\ var c: c_int;
412 \\ c = (a + b);
413 \\ c = (a - b);
414 \\ c = (a * b);
415 \\ c = @divTrunc(a, b);
416 \\ c = @rem(a, b);
417 \\}
418 \\export fn u(a: c_uint, b: c_uint) -> c_uint {
419 \\ var c: c_uint;
420 \\ c = (a +% b);
421 \\ c = (a -% b);
422 \\ c = (a *% b);
423 \\ c = (a / b);
424 \\ c = (a % b);
425 \\}
426 );
427
428 cases.add("bitwise binary operators",
429 \\int max(int a, int b) {
430 \\ return (a & b) ^ (a | b);
431 \\}
432 ,
433 \\export fn max(a: c_int, b: c_int) -> c_int {
434 \\ return (a & b) ^ (a | b);
435 \\}
436 );
437
438 cases.add("logical and, logical or",
439 \\int max(int a, int b) {
440 \\ if (a < b || a == b)
441 \\ return b;
442 \\ if (a >= b && a == b)
443 \\ return a;
444 \\ return a;
445 \\}
446 ,
447 \\export fn max(a: c_int, b: c_int) -> c_int {
448 \\ if ((a < b) or (a == b)) return b;
449 \\ if ((a >= b) and (a == b)) return a;
450 \\ return a;
451 \\}
452 );
453
454 cases.add("assign",
455 \\int max(int a) {
456 \\ int tmp;
457 \\ tmp = a;
458 \\ a = tmp;
459 \\}
460 ,
461 \\export fn max(_arg_a: c_int) -> c_int {
462 \\ var a = _arg_a;
463 \\ var tmp: c_int;
464 \\ tmp = a;
465 \\ a = tmp;
466 \\}
467 );
468
469 cases.add("chaining assign",
470 \\void max(int a) {
471 \\ int b, c;
472 \\ c = b = a;
473 \\}
474 ,
475 \\export fn max(a: c_int) {
476 \\ var b: c_int;
477 \\ var c: c_int;
478 \\ c = {
479 \\ const _tmp = a;
480 \\ b = _tmp;
481 \\ _tmp
482 \\ };
483 \\}
484 );
485
486 cases.add("shift right assign with a fixed size type",
487 \\#include <stdint.h>
488 \\int log2(uint32_t a) {
489 \\ int i = 0;
490 \\ while (a > 0) {
491 \\ a >>= 1;
492 \\ }
493 \\ return i;
494 \\}
495 ,
496 \\export fn log2(_arg_a: u32) -> c_int {
497 \\ var a = _arg_a;
498 \\ var i: c_int = 0;
499 \\ while (a > c_uint(0)) {
500 \\ a >>= u5(1);
501 \\ };
502 \\ return i;
503 \\}
504 );
505
506 cases.add("anonymous enum",
507 \\enum {
508 \\ One,
509 \\ Two,
510 \\};
511 ,
512 \\pub const One = 0;
513 \\pub const Two = 1;
514 );
515
516 cases.add("function call",
517 \\static void bar(void) { }
518 \\void foo(void) { bar(); }
519 ,
520 \\pub fn bar() {}
521 \\export fn foo() {
522 \\ bar();
523 \\}
524 );
525
526 cases.add("field access expression",
527 \\struct Foo {
528 \\ int field;
529 \\};
530 \\int read_field(struct Foo *foo) {
531 \\ return foo->field;
532 \\}
533 ,
534 \\pub const struct_Foo = extern struct {
535 \\ field: c_int,
536 \\};
537 \\export fn read_field(foo: ?&struct_Foo) -> c_int {
538 \\ return (??foo).field;
539 \\}
540 );
541
542 cases.add("null statements",
543 \\void foo(void) {
544 \\ ;;;;;
545 \\}
546 ,
547 \\export fn foo() {}
548 );
549
550 cases.add("undefined array global",
551 \\int array[100];
552 ,
553 \\pub var array: [100]c_int = undefined;
554 );
555
556 cases.add("array access",
557 \\int array[100];
558 \\int foo(int index) {
559 \\ return array[index];
560 \\}
561 ,
562 \\pub var array: [100]c_int = undefined;
563 \\export fn foo(index: c_int) -> c_int {
564 \\ return array[index];
565 \\}
566 );
567
568
569 cases.add("c style cast",
570 \\int float_to_int(float a) {
571 \\ return (int)a;
572 \\}
573 ,
574 \\export fn float_to_int(a: f32) -> c_int {
575 \\ return c_int(a);
576 \\}
577 );
578
579 cases.add("implicit cast to void *",
580 \\void *foo(unsigned short *x) {
581 \\ return x;
582 \\}
583 ,
584 \\export fn foo(x: ?&c_ushort) -> ?&c_void {
585 \\ return @ptrCast(?&c_void, x);
586 \\}
587 );
588
589 cases.add("sizeof",
590 \\#include <stddef.h>
591 \\size_t size_of(void) {
592 \\ return sizeof(int);
593 \\}
594 ,
595 \\export fn size_of() -> usize {
596 \\ return @sizeOf(c_int);
597 \\}
598 );
317}599}
600
601
602
603
604// TODO
605//float *ptrcast(int *a) {
606// return (float *)a;
607//}
608// should translate to
609// fn ptrcast(a: ?&c_int) -> ?&f32 {
610// return @ptrCast(?&f32, a);
611// }
test/tests.zig+2-2
...@@ -780,7 +780,7 @@ pub const ParseCContext = struct {...@@ -780,7 +780,7 @@ pub const ParseCContext = struct {
780 });780 });
781 }781 }
782782
783 pub fn addExpectedError(self: &TestCase, text: []const u8) {783 pub fn addExpectedLine(self: &TestCase, text: []const u8) {
784 %%self.expected_lines.append(text);784 %%self.expected_lines.append(text);
785 }785 }
786 };786 };
...@@ -905,7 +905,7 @@ pub const ParseCContext = struct {...@@ -905,7 +905,7 @@ pub const ParseCContext = struct {
905 tc.addSourceFile("source.h", source);905 tc.addSourceFile("source.h", source);
906 comptime var arg_i = 0;906 comptime var arg_i = 0;
907 inline while (arg_i < expected_lines.len) : (arg_i += 1) {907 inline while (arg_i < expected_lines.len) : (arg_i += 1) {
908 tc.addExpectedError(expected_lines[arg_i]);908 tc.addExpectedLine(expected_lines[arg_i]);
909 }909 }
910 return tc;910 return tc;
911 }911 }