| ... | ... | @@ -118,7 +118,7 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const Stmt *stmt, |
| 118 | 118 | static TransScope *trans_stmt(Context *c, TransScope *scope, const Stmt *stmt, AstNode **out_node); |
| 119 | 119 | static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const Expr *expr, TransLRValue lrval); |
| 120 | 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 | 123 | ATTRIBUTE_PRINTF(3, 4) |
| 124 | 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 | 632 | case BuiltinType::Int128: |
| 633 | 633 | case BuiltinType::WChar_S: |
| 634 | 634 | return true; |
| 635 | | default: |
| 635 | default: |
| 636 | 636 | return false; |
| 637 | 637 | } |
| 638 | 638 | } |
| ... | ... | @@ -653,7 +653,7 @@ static bool c_is_unsigned_integer(Context *c, QualType qt) { |
| 653 | 653 | case BuiltinType::UInt128: |
| 654 | 654 | case BuiltinType::WChar_U: |
| 655 | 655 | return true; |
| 656 | | default: |
| 656 | default: |
| 657 | 657 | return false; |
| 658 | 658 | } |
| 659 | 659 | } |
| ... | ... | @@ -678,7 +678,7 @@ static bool c_is_float(Context *c, QualType qt) { |
| 678 | 678 | case BuiltinType::Float128: |
| 679 | 679 | case BuiltinType::LongDouble: |
| 680 | 680 | return true; |
| 681 | | default: |
| 681 | default: |
| 682 | 682 | return false; |
| 683 | 683 | } |
| 684 | 684 | } |
| ... | ... | @@ -1389,7 +1389,7 @@ static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result |
| 1389 | 1389 | if (result_used == ResultUsedYes) { |
| 1390 | 1390 | // break :x *_ref |
| 1391 | 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 | 1393 | trans_create_node_prefix_op(c, PrefixOpDereference, |
| 1394 | 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 | 1907 | return nullptr; |
| 1908 | 1908 | } |
| 1909 | 1909 | } |
| 1910 | case UO_LNot: |
| 1910 | 1911 | case UO_Not: |
| 1911 | 1912 | { |
| 1912 | 1913 | Expr *op_expr = stmt->getSubExpr(); |
| 1913 | 1914 | AstNode *sub_node = trans_expr(c, ResultUsedYes, scope, op_expr, TransRValue); |
| 1914 | 1915 | if (sub_node == nullptr) |
| 1915 | 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 | 1927 | case UO_Real: |
| 1922 | 1928 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_Real"); |
| 1923 | 1929 | return nullptr; |
| ... | ... | @@ -2197,43 +2203,10 @@ static int trans_local_declaration(Context *c, TransScope *scope, const DeclStmt |
| 2197 | 2203 | return ErrorNone; |
| 2198 | 2204 | } |
| 2199 | 2205 | |
| 2200 | | static AstNode *trans_while_loop(Context *c, TransScope *scope, const WhileStmt *stmt) { |
| 2201 | | TransScopeWhile *while_scope = trans_scope_while_create(c, scope); |
| 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) { |
| 2206 | static AstNode *trans_to_bool_expr(Context *c, TransScope *scope, AstNode *expr) { |
| 2207 | switch (expr->type) { |
| 2235 | 2208 | case NodeTypeBinOpExpr: |
| 2236 | | switch (condition_node->data.bin_op_expr.bin_op) { |
| 2209 | switch (expr->data.bin_op_expr.bin_op) { |
| 2237 | 2210 | case BinOpTypeBoolOr: |
| 2238 | 2211 | case BinOpTypeBoolAnd: |
| 2239 | 2212 | case BinOpTypeCmpEq: |
| ... | ... | @@ -2242,43 +2215,42 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt * |
| 2242 | 2215 | case BinOpTypeCmpGreaterThan: |
| 2243 | 2216 | case BinOpTypeCmpLessOrEq: |
| 2244 | 2217 | case BinOpTypeCmpGreaterOrEq: |
| 2245 | | if_node->data.if_bool_expr.condition = condition_node; |
| 2246 | | return if_node; |
| 2218 | return expr; |
| 2247 | 2219 | default: |
| 2248 | 2220 | goto convert_to_bitcast; |
| 2249 | 2221 | } |
| 2250 | 2222 | |
| 2251 | 2223 | case NodeTypePrefixOpExpr: |
| 2252 | | switch (condition_node->data.prefix_op_expr.prefix_op) { |
| 2224 | switch (expr->data.prefix_op_expr.prefix_op) { |
| 2253 | 2225 | case PrefixOpBoolNot: |
| 2254 | | if_node->data.if_bool_expr.condition = condition_node; |
| 2255 | | return if_node; |
| 2226 | return expr; |
| 2256 | 2227 | default: |
| 2257 | 2228 | goto convert_to_bitcast; |
| 2258 | 2229 | } |
| 2259 | 2230 | |
| 2260 | 2231 | case NodeTypeBoolLiteral: |
| 2261 | | if_node->data.if_bool_expr.condition = condition_node; |
| 2262 | | return if_node; |
| 2232 | return expr; |
| 2263 | 2233 | |
| 2264 | 2234 | default: { |
| 2265 | | // In Zig, float, int and pointer does not work in if statements. |
| 2266 | | // To make it work, we bitcast any value we get to an int of the right size |
| 2267 | | // and comp it to 0 |
| 2268 | | // TODO: This doesn't work for pointers, as they become nullable on |
| 2269 | | // translate |
| 2270 | | // c: if (cond) { } |
| 2271 | | // zig: { |
| 2272 | | // zig: const _tmp = cond; |
| 2273 | | // zig: if (@bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0) { } |
| 2274 | | // zig: } |
| 2275 | | convert_to_bitcast: |
| 2235 | // In Zig, float, int and pointer does not implicitly cast to bool. |
| 2236 | // To make it work, we bitcast any value we get to an int of the right size |
| 2237 | // and comp it to 0 |
| 2238 | // TODO: This doesn't work for pointers, as they become nullable on |
| 2239 | // translate |
| 2240 | // c: expr |
| 2241 | // zig: __to_bool_expr: { |
| 2242 | // zig: const _tmp = cond; |
| 2243 | // zig: break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0; |
| 2244 | // zig: } |
| 2245 | convert_to_bitcast: |
| 2276 | 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 | 2250 | // const _tmp = cond; |
| 2279 | 2251 | // TODO: avoid name collisions with generated variable names |
| 2280 | | 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); |
| 2252 | Buf *tmp_var_name = buf_create_from_str("_tmp"); |
| 2253 | AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, expr); |
| 2282 | 2254 | child_scope->node->data.block.statements.append(tmp_var_decl); |
| 2283 | 2255 | |
| 2284 | 2256 | // @sizeOf(@typeOf(_tmp)) * 8 |
| ... | ... | @@ -2287,8 +2259,8 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt * |
| 2287 | 2259 | AstNode *sizeof_tmp = trans_create_node_builtin_fn_call_str(c, "sizeOf"); |
| 2288 | 2260 | sizeof_tmp->data.fn_call_expr.params.append(typeof_tmp); |
| 2289 | 2261 | AstNode *sizeof_tmp_in_bits = trans_create_node_bin_op( |
| 2290 | | c, sizeof_tmp, BinOpTypeMult, |
| 2291 | | trans_create_node_unsigned_negative(c, 8, false)); |
| 2262 | c, sizeof_tmp, BinOpTypeMult, |
| 2263 | trans_create_node_unsigned_negative(c, 8, false)); |
| 2292 | 2264 | |
| 2293 | 2265 | // @IntType(false, @sizeOf(@typeOf(_tmp)) * 8) |
| 2294 | 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 | 2272 | bit_cast->data.fn_call_expr.params.append(int_type); |
| 2301 | 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 | 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; |
| 2306 | | child_scope->node->data.block.statements.append(if_node); |
| 2277 | child_scope->node->data.block.statements.append(trans_create_node_break(c, label_name, not_eql_zero)); |
| 2307 | 2278 | |
| 2308 | 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 | 2322 | static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *scope, const CallExpr *stmt) { |
| 2314 | 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 | 2505 | &while_scope->node->data.while_expr.condition); |
| 2497 | 2506 | if (end_cond_scope == nullptr) |
| 2498 | 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 | 2512 | const Stmt *inc_stmt = stmt->getInc(); |