| ... | @@ -118,7 +118,7 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const Stmt *stmt, | ... | @@ -118,7 +118,7 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const Stmt *stmt, |
| 118 | static TransScope *trans_stmt(Context *c, TransScope *scope, const Stmt *stmt, AstNode **out_node); | 118 | static TransScope *trans_stmt(Context *c, TransScope *scope, const Stmt *stmt, AstNode **out_node); |
| 119 | static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const Expr *expr, TransLRValue lrval); | 119 | static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const Expr *expr, TransLRValue lrval); |
| 120 | static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc); | 120 | static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc); |
| 121 | | 121 | static AstNode *trans_to_bool_expr(Context *c, TransScope *scope, AstNode *expr); |
| 122 | | 122 | |
| 123 | ATTRIBUTE_PRINTF(3, 4) | 123 | ATTRIBUTE_PRINTF(3, 4) |
| 124 | static void emit_warning(Context *c, const SourceLocation &sl, const char *format, ...) { | 124 | static void emit_warning(Context *c, const SourceLocation &sl, const char *format, ...) { |
| ... | @@ -632,7 +632,7 @@ static bool c_is_signed_integer(Context *c, QualType qt) { | ... | @@ -632,7 +632,7 @@ static bool c_is_signed_integer(Context *c, QualType qt) { |
| 632 | case BuiltinType::Int128: | 632 | case BuiltinType::Int128: |
| 633 | case BuiltinType::WChar_S: | 633 | case BuiltinType::WChar_S: |
| 634 | return true; | 634 | return true; |
| 635 | default: | 635 | default: |
| 636 | return false; | 636 | return false; |
| 637 | } | 637 | } |
| 638 | } | 638 | } |
| ... | @@ -653,7 +653,7 @@ static bool c_is_unsigned_integer(Context *c, QualType qt) { | ... | @@ -653,7 +653,7 @@ static bool c_is_unsigned_integer(Context *c, QualType qt) { |
| 653 | case BuiltinType::UInt128: | 653 | case BuiltinType::UInt128: |
| 654 | case BuiltinType::WChar_U: | 654 | case BuiltinType::WChar_U: |
| 655 | return true; | 655 | return true; |
| 656 | default: | 656 | default: |
| 657 | return false; | 657 | return false; |
| 658 | } | 658 | } |
| 659 | } | 659 | } |
| ... | @@ -678,7 +678,7 @@ static bool c_is_float(Context *c, QualType qt) { | ... | @@ -678,7 +678,7 @@ static bool c_is_float(Context *c, QualType qt) { |
| 678 | case BuiltinType::Float128: | 678 | case BuiltinType::Float128: |
| 679 | case BuiltinType::LongDouble: | 679 | case BuiltinType::LongDouble: |
| 680 | return true; | 680 | return true; |
| 681 | default: | 681 | default: |
| 682 | return false; | 682 | return false; |
| 683 | } | 683 | } |
| 684 | } | 684 | } |
| ... | @@ -1389,7 +1389,7 @@ static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result | ... | @@ -1389,7 +1389,7 @@ static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result |
| 1389 | if (result_used == ResultUsedYes) { | 1389 | if (result_used == ResultUsedYes) { |
| 1390 | // break :x *_ref | 1390 | // break :x *_ref |
| 1391 | child_scope->node->data.block.statements.append( | 1391 | child_scope->node->data.block.statements.append( |
| 1392 | trans_create_node_break(c, label_name, | 1392 | trans_create_node_break(c, label_name, |
| 1393 | trans_create_node_prefix_op(c, PrefixOpDereference, | 1393 | trans_create_node_prefix_op(c, PrefixOpDereference, |
| 1394 | trans_create_node_symbol(c, tmp_var_name)))); | 1394 | trans_create_node_symbol(c, tmp_var_name)))); |
| 1395 | } | 1395 | } |
| ... | @@ -1907,17 +1907,23 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc | ... | @@ -1907,17 +1907,23 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc |
| 1907 | return nullptr; | 1907 | return nullptr; |
| 1908 | } | 1908 | } |
| 1909 | } | 1909 | } |
| | 1910 | case UO_LNot: |
| 1910 | case UO_Not: | 1911 | case UO_Not: |
| 1911 | { | 1912 | { |
| 1912 | Expr *op_expr = stmt->getSubExpr(); | 1913 | Expr *op_expr = stmt->getSubExpr(); |
| 1913 | AstNode *sub_node = trans_expr(c, ResultUsedYes, scope, op_expr, TransRValue); | 1914 | AstNode *sub_node = trans_expr(c, ResultUsedYes, scope, op_expr, TransRValue); |
| 1914 | if (sub_node == nullptr) | 1915 | if (sub_node == nullptr) |
| 1915 | return nullptr; | 1916 | return nullptr; |
| 1916 | return trans_create_node_prefix_op(c, PrefixOpBinNot, sub_node); | 1917 | |
| | 1918 | switch (stmt->getOpcode()) { |
| | 1919 | case UO_LNot: |
| | 1920 | return trans_create_node_prefix_op(c, PrefixOpBoolNot, trans_to_bool_expr(c, scope, sub_node)); |
| | 1921 | case UO_Not: |
| | 1922 | return trans_create_node_prefix_op(c, PrefixOpBinNot, sub_node); |
| | 1923 | default: |
| | 1924 | zig_unreachable(); |
| | 1925 | } |
| 1917 | } | 1926 | } |
| 1918 | case UO_LNot: | | |
| 1919 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_LNot"); | | |
| 1920 | return nullptr; | | |
| 1921 | case UO_Real: | 1927 | case UO_Real: |
| 1922 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_Real"); | 1928 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_Real"); |
| 1923 | return nullptr; | 1929 | return nullptr; |
| ... | @@ -2197,43 +2203,10 @@ static int trans_local_declaration(Context *c, TransScope *scope, const DeclStmt | ... | @@ -2197,43 +2203,10 @@ static int trans_local_declaration(Context *c, TransScope *scope, const DeclStmt |
| 2197 | return ErrorNone; | 2203 | return ErrorNone; |
| 2198 | } | 2204 | } |
| 2199 | | 2205 | |
| 2200 | static AstNode *trans_while_loop(Context *c, TransScope *scope, const WhileStmt *stmt) { | 2206 | static AstNode *trans_to_bool_expr(Context *c, TransScope *scope, AstNode *expr) { |
| 2201 | TransScopeWhile *while_scope = trans_scope_while_create(c, scope); | 2207 | switch (expr->type) { |
| 2202 | | | |
| 2203 | while_scope->node->data.while_expr.condition = trans_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue); | | |
| 2204 | if (while_scope->node->data.while_expr.condition == nullptr) | | |
| 2205 | return nullptr; | | |
| 2206 | | | |
| 2207 | TransScope *body_scope = trans_stmt(c, &while_scope->base, stmt->getBody(), | | |
| 2208 | &while_scope->node->data.while_expr.body); | | |
| 2209 | if (body_scope == nullptr) | | |
| 2210 | return nullptr; | | |
| 2211 | | | |
| 2212 | return while_scope->node; | | |
| 2213 | } | | |
| 2214 | | | |
| 2215 | static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt *stmt) { | | |
| 2216 | // if (c) t | | |
| 2217 | // if (c) t else e | | |
| 2218 | AstNode *if_node = trans_create_node(c, NodeTypeIfBoolExpr); | | |
| 2219 | | | |
| 2220 | TransScope *then_scope = trans_stmt(c, scope, stmt->getThen(), &if_node->data.if_bool_expr.then_block); | | |
| 2221 | if (then_scope == nullptr) | | |
| 2222 | return nullptr; | | |
| 2223 | | | |
| 2224 | if (stmt->getElse() != nullptr) { | | |
| 2225 | TransScope *else_scope = trans_stmt(c, scope, stmt->getElse(), &if_node->data.if_bool_expr.else_node); | | |
| 2226 | if (else_scope == nullptr) | | |
| 2227 | return nullptr; | | |
| 2228 | } | | |
| 2229 | | | |
| 2230 | AstNode *condition_node = trans_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue); | | |
| 2231 | if (condition_node == nullptr) | | |
| 2232 | return nullptr; | | |
| 2233 | | | |
| 2234 | switch (condition_node->type) { | | |
| 2235 | case NodeTypeBinOpExpr: | 2208 | case NodeTypeBinOpExpr: |
| 2236 | switch (condition_node->data.bin_op_expr.bin_op) { | 2209 | switch (expr->data.bin_op_expr.bin_op) { |
| 2237 | case BinOpTypeBoolOr: | 2210 | case BinOpTypeBoolOr: |
| 2238 | case BinOpTypeBoolAnd: | 2211 | case BinOpTypeBoolAnd: |
| 2239 | case BinOpTypeCmpEq: | 2212 | case BinOpTypeCmpEq: |
| ... | @@ -2242,43 +2215,42 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt * | ... | @@ -2242,43 +2215,42 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt * |
| 2242 | case BinOpTypeCmpGreaterThan: | 2215 | case BinOpTypeCmpGreaterThan: |
| 2243 | case BinOpTypeCmpLessOrEq: | 2216 | case BinOpTypeCmpLessOrEq: |
| 2244 | case BinOpTypeCmpGreaterOrEq: | 2217 | case BinOpTypeCmpGreaterOrEq: |
| 2245 | if_node->data.if_bool_expr.condition = condition_node; | 2218 | return expr; |
| 2246 | return if_node; | | |
| 2247 | default: | 2219 | default: |
| 2248 | goto convert_to_bitcast; | 2220 | goto convert_to_bitcast; |
| 2249 | } | 2221 | } |
| 2250 | | 2222 | |
| 2251 | case NodeTypePrefixOpExpr: | 2223 | case NodeTypePrefixOpExpr: |
| 2252 | switch (condition_node->data.prefix_op_expr.prefix_op) { | 2224 | switch (expr->data.prefix_op_expr.prefix_op) { |
| 2253 | case PrefixOpBoolNot: | 2225 | case PrefixOpBoolNot: |
| 2254 | if_node->data.if_bool_expr.condition = condition_node; | 2226 | return expr; |
| 2255 | return if_node; | | |
| 2256 | default: | 2227 | default: |
| 2257 | goto convert_to_bitcast; | 2228 | goto convert_to_bitcast; |
| 2258 | } | 2229 | } |
| 2259 | | 2230 | |
| 2260 | case NodeTypeBoolLiteral: | 2231 | case NodeTypeBoolLiteral: |
| 2261 | if_node->data.if_bool_expr.condition = condition_node; | 2232 | return expr; |
| 2262 | return if_node; | | |
| 2263 | | 2233 | |
| 2264 | default: { | 2234 | default: { |
| 2265 | // In Zig, float, int and pointer does not work in if statements. | 2235 | // In Zig, float, int and pointer does not implicitly cast to bool. |
| 2266 | // To make it work, we bitcast any value we get to an int of the right size | 2236 | // To make it work, we bitcast any value we get to an int of the right size |
| 2267 | // and comp it to 0 | 2237 | // and comp it to 0 |
| 2268 | // TODO: This doesn't work for pointers, as they become nullable on | 2238 | // TODO: This doesn't work for pointers, as they become nullable on |
| 2269 | // translate | 2239 | // translate |
| 2270 | // c: if (cond) { } | 2240 | // c: expr |
| 2271 | // zig: { | 2241 | // zig: __to_bool_expr: { |
| 2272 | // zig: const _tmp = cond; | 2242 | // zig: const _tmp = cond; |
| 2273 | // zig: if (@bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0) { } | 2243 | // zig: break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0; |
| 2274 | // zig: } | 2244 | // zig: } |
| 2275 | convert_to_bitcast: | 2245 | convert_to_bitcast: |
| 2276 | TransScopeBlock *child_scope = trans_scope_block_create(c, scope); | 2246 | TransScopeBlock *child_scope = trans_scope_block_create(c, scope); |
| | 2247 | Buf *label_name = buf_create_from_str("__to_bool_expr"); |
| | 2248 | child_scope->node->data.block.name = label_name; |
| 2277 | | 2249 | |
| 2278 | // const _tmp = cond; | 2250 | // const _tmp = cond; |
| 2279 | // TODO: avoid name collisions with generated variable names | 2251 | // TODO: avoid name collisions with generated variable names |
| 2280 | Buf* tmp_var_name = buf_create_from_str("_tmp"); | 2252 | Buf *tmp_var_name = buf_create_from_str("_tmp"); |
| 2281 | AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, condition_node); | 2253 | AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, expr); |
| 2282 | child_scope->node->data.block.statements.append(tmp_var_decl); | 2254 | child_scope->node->data.block.statements.append(tmp_var_decl); |
| 2283 | | 2255 | |
| 2284 | // @sizeOf(@typeOf(_tmp)) * 8 | 2256 | // @sizeOf(@typeOf(_tmp)) * 8 |
| ... | @@ -2287,8 +2259,8 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt * | ... | @@ -2287,8 +2259,8 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt * |
| 2287 | AstNode *sizeof_tmp = trans_create_node_builtin_fn_call_str(c, "sizeOf"); | 2259 | AstNode *sizeof_tmp = trans_create_node_builtin_fn_call_str(c, "sizeOf"); |
| 2288 | sizeof_tmp->data.fn_call_expr.params.append(typeof_tmp); | 2260 | sizeof_tmp->data.fn_call_expr.params.append(typeof_tmp); |
| 2289 | AstNode *sizeof_tmp_in_bits = trans_create_node_bin_op( | 2261 | AstNode *sizeof_tmp_in_bits = trans_create_node_bin_op( |
| 2290 | c, sizeof_tmp, BinOpTypeMult, | 2262 | c, sizeof_tmp, BinOpTypeMult, |
| 2291 | trans_create_node_unsigned_negative(c, 8, false)); | 2263 | trans_create_node_unsigned_negative(c, 8, false)); |
| 2292 | | 2264 | |
| 2293 | // @IntType(false, @sizeOf(@typeOf(_tmp)) * 8) | 2265 | // @IntType(false, @sizeOf(@typeOf(_tmp)) * 8) |
| 2294 | AstNode *int_type = trans_create_node_builtin_fn_call_str(c, "IntType"); | 2266 | AstNode *int_type = trans_create_node_builtin_fn_call_str(c, "IntType"); |
| ... | @@ -2300,16 +2272,53 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt * | ... | @@ -2300,16 +2272,53 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt * |
| 2300 | bit_cast->data.fn_call_expr.params.append(int_type); | 2272 | bit_cast->data.fn_call_expr.params.append(int_type); |
| 2301 | bit_cast->data.fn_call_expr.params.append(trans_create_node_symbol(c, tmp_var_name)); | 2273 | bit_cast->data.fn_call_expr.params.append(trans_create_node_symbol(c, tmp_var_name)); |
| 2302 | | 2274 | |
| 2303 | // if (@bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0) { } | 2275 | // break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0 |
| 2304 | AstNode *not_eql_zero = trans_create_node_bin_op(c, bit_cast, BinOpTypeCmpNotEq, trans_create_node_unsigned_negative(c, 0, false)); | 2276 | AstNode *not_eql_zero = trans_create_node_bin_op(c, bit_cast, BinOpTypeCmpNotEq, trans_create_node_unsigned_negative(c, 0, false)); |
| 2305 | if_node->data.if_bool_expr.condition = not_eql_zero; | 2277 | child_scope->node->data.block.statements.append(trans_create_node_break(c, label_name, not_eql_zero)); |
| 2306 | child_scope->node->data.block.statements.append(if_node); | | |
| 2307 | | 2278 | |
| 2308 | return child_scope->node; | 2279 | return child_scope->node; |
| 2309 | } | 2280 | } |
| 2310 | } | 2281 | } |
| 2311 | } | 2282 | } |
| 2312 | | 2283 | |
| | 2284 | static AstNode *trans_while_loop(Context *c, TransScope *scope, const WhileStmt *stmt) { |
| | 2285 | TransScopeWhile *while_scope = trans_scope_while_create(c, scope); |
| | 2286 | |
| | 2287 | while_scope->node->data.while_expr.condition = trans_to_bool_expr(c, scope, trans_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue)); |
| | 2288 | if (while_scope->node->data.while_expr.condition == nullptr) |
| | 2289 | return nullptr; |
| | 2290 | |
| | 2291 | TransScope *body_scope = trans_stmt(c, &while_scope->base, stmt->getBody(), |
| | 2292 | &while_scope->node->data.while_expr.body); |
| | 2293 | if (body_scope == nullptr) |
| | 2294 | return nullptr; |
| | 2295 | |
| | 2296 | return while_scope->node; |
| | 2297 | } |
| | 2298 | |
| | 2299 | static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt *stmt) { |
| | 2300 | // if (c) t |
| | 2301 | // if (c) t else e |
| | 2302 | AstNode *if_node = trans_create_node(c, NodeTypeIfBoolExpr); |
| | 2303 | |
| | 2304 | TransScope *then_scope = trans_stmt(c, scope, stmt->getThen(), &if_node->data.if_bool_expr.then_block); |
| | 2305 | if (then_scope == nullptr) |
| | 2306 | return nullptr; |
| | 2307 | |
| | 2308 | if (stmt->getElse() != nullptr) { |
| | 2309 | TransScope *else_scope = trans_stmt(c, scope, stmt->getElse(), &if_node->data.if_bool_expr.else_node); |
| | 2310 | if (else_scope == nullptr) |
| | 2311 | return nullptr; |
| | 2312 | } |
| | 2313 | |
| | 2314 | AstNode *condition_node = trans_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue); |
| | 2315 | if (condition_node == nullptr) |
| | 2316 | return nullptr; |
| | 2317 | |
| | 2318 | if_node->data.if_bool_expr.condition = trans_to_bool_expr(c, scope, condition_node); |
| | 2319 | return if_node; |
| | 2320 | } |
| | 2321 | |
| 2313 | static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *scope, const CallExpr *stmt) { | 2322 | static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *scope, const CallExpr *stmt) { |
| 2314 | AstNode *node = trans_create_node(c, NodeTypeFnCallExpr); | 2323 | AstNode *node = trans_create_node(c, NodeTypeFnCallExpr); |
| 2315 | | 2324 | |
| ... | @@ -2496,6 +2505,8 @@ static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForSt | ... | @@ -2496,6 +2505,8 @@ static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForSt |
| 2496 | &while_scope->node->data.while_expr.condition); | 2505 | &while_scope->node->data.while_expr.condition); |
| 2497 | if (end_cond_scope == nullptr) | 2506 | if (end_cond_scope == nullptr) |
| 2498 | return nullptr; | 2507 | return nullptr; |
| | 2508 | |
| | 2509 | while_scope->node->data.while_expr.condition = trans_to_bool_expr(c, cond_scope, while_scope->node->data.while_expr.condition); |
| 2499 | } | 2510 | } |
| 2500 | | 2511 | |
| 2501 | const Stmt *inc_stmt = stmt->getInc(); | 2512 | const Stmt *inc_stmt = stmt->getInc(); |