authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-01-16 10:32:37-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2018-01-16 10:32:37-05:00
logee9ab15679ee04a40bdc582779faf43fb10836ce
treee9ed503ecbeb4b5ce2dcbefd953670d834fc5cb6
parent8b280d5b31858e1224ab97051df78ea29114e908
parent3974b7d31d5b163989255c9a164a8db15bd0ddf1
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #695 from Hejsil/tranlate-c-fixes

Tranlate c fixes - undefined variable initialization and non-bool if statements

2 files changed, 109 insertions(+), 12 deletions(-)

src/translate_c.cpp+83-7
...@@ -1955,6 +1955,8 @@ static int trans_local_declaration(Context *c, TransScope *scope, const DeclStmt...@@ -1955,6 +1955,8 @@ static int trans_local_declaration(Context *c, TransScope *scope, const DeclStmt
1955 if (init_node == nullptr)1955 if (init_node == nullptr)
1956 return ErrorUnexpected;1956 return ErrorUnexpected;
19571957
1958 } else {
1959 init_node = trans_create_node(c, NodeTypeUndefinedLiteral);
1958 }1960 }
1959 AstNode *type_node = trans_qual_type(c, qual_type, stmt->getLocStart());1961 AstNode *type_node = trans_qual_type(c, qual_type, stmt->getLocStart());
1960 if (type_node == nullptr)1962 if (type_node == nullptr)
...@@ -2215,12 +2217,6 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt *...@@ -2215,12 +2217,6 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt *
2215 // if (c) t else e2217 // if (c) t else e
2216 AstNode *if_node = trans_create_node(c, NodeTypeIfBoolExpr);2218 AstNode *if_node = trans_create_node(c, NodeTypeIfBoolExpr);
22172219
2218 // TODO: condition != 0
2219 AstNode *condition_node = trans_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue);
2220 if (condition_node == nullptr)
2221 return nullptr;
2222 if_node->data.if_bool_expr.condition = condition_node;
2223
2224 TransScope *then_scope = trans_stmt(c, scope, stmt->getThen(), &if_node->data.if_bool_expr.then_block);2220 TransScope *then_scope = trans_stmt(c, scope, stmt->getThen(), &if_node->data.if_bool_expr.then_block);
2225 if (then_scope == nullptr)2221 if (then_scope == nullptr)
2226 return nullptr;2222 return nullptr;
...@@ -2231,7 +2227,87 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt *...@@ -2231,7 +2227,87 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt *
2231 return nullptr;2227 return nullptr;
2232 }2228 }
22332229
2234 return if_node;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:
2236 switch (condition_node->data.bin_op_expr.bin_op) {
2237 case BinOpTypeBoolOr:
2238 case BinOpTypeBoolAnd:
2239 case BinOpTypeCmpEq:
2240 case BinOpTypeCmpNotEq:
2241 case BinOpTypeCmpLessThan:
2242 case BinOpTypeCmpGreaterThan:
2243 case BinOpTypeCmpLessOrEq:
2244 case BinOpTypeCmpGreaterOrEq:
2245 if_node->data.if_bool_expr.condition = condition_node;
2246 return if_node;
2247 default:
2248 goto convert_to_bitcast;
2249 }
2250
2251 case NodeTypePrefixOpExpr:
2252 switch (condition_node->data.prefix_op_expr.prefix_op) {
2253 case PrefixOpBoolNot:
2254 if_node->data.if_bool_expr.condition = condition_node;
2255 return if_node;
2256 default:
2257 goto convert_to_bitcast;
2258 }
2259
2260 case NodeTypeBoolLiteral:
2261 if_node->data.if_bool_expr.condition = condition_node;
2262 return if_node;
2263
2264 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:
2276 TransScopeBlock *child_scope = trans_scope_block_create(c, scope);
2277
2278 // const _tmp = cond;
2279 // 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);
2282 child_scope->node->data.block.statements.append(tmp_var_decl);
2283
2284 // @sizeOf(@typeOf(_tmp)) * 8
2285 AstNode *typeof_tmp = trans_create_node_builtin_fn_call_str(c, "typeOf");
2286 typeof_tmp->data.fn_call_expr.params.append(trans_create_node_symbol(c, tmp_var_name));
2287 AstNode *sizeof_tmp = trans_create_node_builtin_fn_call_str(c, "sizeOf");
2288 sizeof_tmp->data.fn_call_expr.params.append(typeof_tmp);
2289 AstNode *sizeof_tmp_in_bits = trans_create_node_bin_op(
2290 c, sizeof_tmp, BinOpTypeMult,
2291 trans_create_node_unsigned_negative(c, 8, false));
2292
2293 // @IntType(false, @sizeOf(@typeOf(_tmp)) * 8)
2294 AstNode *int_type = trans_create_node_builtin_fn_call_str(c, "IntType");
2295 int_type->data.fn_call_expr.params.append(trans_create_node_bool(c, false));
2296 int_type->data.fn_call_expr.params.append(sizeof_tmp_in_bits);
2297
2298 // @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp)
2299 AstNode *bit_cast = trans_create_node_builtin_fn_call_str(c, "bitCast");
2300 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));
2302
2303 // if (@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));
2305 if_node->data.if_bool_expr.condition = not_eql_zero;
2306 child_scope->node->data.block.statements.append(if_node);
2307
2308 return child_scope->node;
2309 }
2310 }
2235}2311}
22362312
2237static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *scope, const CallExpr *stmt) {2313static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *scope, const CallExpr *stmt) {
test/translate_c.zig+26-5
...@@ -408,7 +408,7 @@ pub fn addCases(cases: &tests.TranslateCContext) {...@@ -408,7 +408,7 @@ pub fn addCases(cases: &tests.TranslateCContext) {
408 \\}408 \\}
409 ,409 ,
410 \\pub export fn s(a: c_int, b: c_int) -> c_int {410 \\pub export fn s(a: c_int, b: c_int) -> c_int {
411 \\ var c: c_int;411 \\ var c: c_int = undefined;
412 \\ c = (a + b);412 \\ c = (a + b);
413 \\ c = (a - b);413 \\ c = (a - b);
414 \\ c = (a * b);414 \\ c = (a * b);
...@@ -416,7 +416,7 @@ pub fn addCases(cases: &tests.TranslateCContext) {...@@ -416,7 +416,7 @@ pub fn addCases(cases: &tests.TranslateCContext) {
416 \\ c = @rem(a, b);416 \\ c = @rem(a, b);
417 \\}417 \\}
418 \\pub export fn u(a: c_uint, b: c_uint) -> c_uint {418 \\pub export fn u(a: c_uint, b: c_uint) -> c_uint {
419 \\ var c: c_uint;419 \\ var c: c_uint = undefined;
420 \\ c = (a +% b);420 \\ c = (a +% b);
421 \\ c = (a -% b);421 \\ c = (a -% b);
422 \\ c = (a *% b);422 \\ c = (a *% b);
...@@ -460,7 +460,7 @@ pub fn addCases(cases: &tests.TranslateCContext) {...@@ -460,7 +460,7 @@ pub fn addCases(cases: &tests.TranslateCContext) {
460 ,460 ,
461 \\pub export fn max(_arg_a: c_int) -> c_int {461 \\pub export fn max(_arg_a: c_int) -> c_int {
462 \\ var a = _arg_a;462 \\ var a = _arg_a;
463 \\ var tmp: c_int;463 \\ var tmp: c_int = undefined;
464 \\ tmp = a;464 \\ tmp = a;
465 \\ a = tmp;465 \\ a = tmp;
466 \\}466 \\}
...@@ -473,8 +473,8 @@ pub fn addCases(cases: &tests.TranslateCContext) {...@@ -473,8 +473,8 @@ pub fn addCases(cases: &tests.TranslateCContext) {
473 \\}473 \\}
474 ,474 ,
475 \\pub export fn max(a: c_int) {475 \\pub export fn max(a: c_int) {
476 \\ var b: c_int;476 \\ var b: c_int = undefined;
477 \\ var c: c_int;477 \\ var c: c_int = undefined;
478 \\ c = x: {478 \\ c = x: {
479 \\ const _tmp = a;479 \\ const _tmp = a;
480 \\ b = _tmp;480 \\ b = _tmp;
...@@ -1114,4 +1114,25 @@ pub fn addCases(cases: &tests.TranslateCContext) {...@@ -1114,4 +1114,25 @@ pub fn addCases(cases: &tests.TranslateCContext) {
1114 ,1114 ,
1115 \\pub const NRF_GPIO = if (@typeId(@typeOf(NRF_GPIO_BASE)) == @import("builtin").TypeId.Pointer) @ptrCast(&NRF_GPIO_Type, NRF_GPIO_BASE) else if (@typeId(@typeOf(NRF_GPIO_BASE)) == @import("builtin").TypeId.Int) @intToPtr(&NRF_GPIO_Type, NRF_GPIO_BASE) else (&NRF_GPIO_Type)(NRF_GPIO_BASE);1115 \\pub const NRF_GPIO = if (@typeId(@typeOf(NRF_GPIO_BASE)) == @import("builtin").TypeId.Pointer) @ptrCast(&NRF_GPIO_Type, NRF_GPIO_BASE) else if (@typeId(@typeOf(NRF_GPIO_BASE)) == @import("builtin").TypeId.Int) @intToPtr(&NRF_GPIO_Type, NRF_GPIO_BASE) else (&NRF_GPIO_Type)(NRF_GPIO_BASE);
1116 );1116 );
1117
1118 cases.add("if on int",
1119 \\int if_int(int i) {
1120 \\ if (i) {
1121 \\ return 0;
1122 \\ } else {
1123 \\ return 1;
1124 \\ }
1125 \\}
1126 ,
1127 \\pub fn if_int(i: c_int) -> c_int {
1128 \\ {
1129 \\ const _tmp = i;
1130 \\ if (@bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0) {
1131 \\ return 0;
1132 \\ } else {
1133 \\ return 1;
1134 \\ };
1135 \\ };
1136 \\}
1137 );
1117}1138}