Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: ziglang/zig
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 8b280d5b3185
Choose a base ref
...
head repository: ziglang/zig
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: ee9ab15679ee
Choose a head ref
  • 4 commits
  • 2 files changed
  • 2 contributors

Commits on Jan 16, 2018

  1. Copy the full SHA
    821cbd7 View commit details
  2. Copy the full SHA
    f59dcc5 View commit details
  3. Copy the full SHA
    3974b7d View commit details
  4. Merge pull request #695 from Hejsil/tranlate-c-fixes

    Tranlate c fixes - undefined variable initialization and non-bool if statements
    andrewrk authored Jan 16, 2018

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    ee9ab15 View commit details
Showing with 109 additions and 12 deletions.
  1. +83 −7 src/translate_c.cpp
  2. +26 −5 test/translate_c.zig
90 changes: 83 additions & 7 deletions src/translate_c.cpp
Original file line number Diff line number Diff line change
@@ -1955,6 +1955,8 @@ static int trans_local_declaration(Context *c, TransScope *scope, const DeclStmt
if (init_node == nullptr)
return ErrorUnexpected;

} else {
init_node = trans_create_node(c, NodeTypeUndefinedLiteral);
}
AstNode *type_node = trans_qual_type(c, qual_type, stmt->getLocStart());
if (type_node == nullptr)
@@ -2215,12 +2217,6 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt *
// if (c) t else e
AstNode *if_node = trans_create_node(c, NodeTypeIfBoolExpr);

// TODO: condition != 0
AstNode *condition_node = trans_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue);
if (condition_node == nullptr)
return nullptr;
if_node->data.if_bool_expr.condition = condition_node;

TransScope *then_scope = trans_stmt(c, scope, stmt->getThen(), &if_node->data.if_bool_expr.then_block);
if (then_scope == nullptr)
return nullptr;
@@ -2231,7 +2227,87 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt *
return nullptr;
}

return if_node;
AstNode *condition_node = trans_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue);
if (condition_node == nullptr)
return nullptr;

switch (condition_node->type) {
case NodeTypeBinOpExpr:
switch (condition_node->data.bin_op_expr.bin_op) {
case BinOpTypeBoolOr:
case BinOpTypeBoolAnd:
case BinOpTypeCmpEq:
case BinOpTypeCmpNotEq:
case BinOpTypeCmpLessThan:
case BinOpTypeCmpGreaterThan:
case BinOpTypeCmpLessOrEq:
case BinOpTypeCmpGreaterOrEq:
if_node->data.if_bool_expr.condition = condition_node;
return if_node;
default:
goto convert_to_bitcast;
}

case NodeTypePrefixOpExpr:
switch (condition_node->data.prefix_op_expr.prefix_op) {
case PrefixOpBoolNot:
if_node->data.if_bool_expr.condition = condition_node;
return if_node;
default:
goto convert_to_bitcast;
}

case NodeTypeBoolLiteral:
if_node->data.if_bool_expr.condition = condition_node;
return if_node;

default: {
// In Zig, float, int and pointer does not work in if statements.
// To make it work, we bitcast any value we get to an int of the right size
// and comp it to 0
// TODO: This doesn't work for pointers, as they become nullable on
// translate
// c: if (cond) { }
// zig: {
// zig: const _tmp = cond;
// zig: if (@bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0) { }
// zig: }
convert_to_bitcast:
TransScopeBlock *child_scope = trans_scope_block_create(c, scope);

// const _tmp = cond;
// TODO: avoid name collisions with generated variable names
Buf* tmp_var_name = buf_create_from_str("_tmp");
AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, condition_node);
child_scope->node->data.block.statements.append(tmp_var_decl);

// @sizeOf(@typeOf(_tmp)) * 8
AstNode *typeof_tmp = trans_create_node_builtin_fn_call_str(c, "typeOf");
typeof_tmp->data.fn_call_expr.params.append(trans_create_node_symbol(c, tmp_var_name));
AstNode *sizeof_tmp = trans_create_node_builtin_fn_call_str(c, "sizeOf");
sizeof_tmp->data.fn_call_expr.params.append(typeof_tmp);
AstNode *sizeof_tmp_in_bits = trans_create_node_bin_op(
c, sizeof_tmp, BinOpTypeMult,
trans_create_node_unsigned_negative(c, 8, false));

// @IntType(false, @sizeOf(@typeOf(_tmp)) * 8)
AstNode *int_type = trans_create_node_builtin_fn_call_str(c, "IntType");
int_type->data.fn_call_expr.params.append(trans_create_node_bool(c, false));
int_type->data.fn_call_expr.params.append(sizeof_tmp_in_bits);

// @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp)
AstNode *bit_cast = trans_create_node_builtin_fn_call_str(c, "bitCast");
bit_cast->data.fn_call_expr.params.append(int_type);
bit_cast->data.fn_call_expr.params.append(trans_create_node_symbol(c, tmp_var_name));

// if (@bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0) { }
AstNode *not_eql_zero = trans_create_node_bin_op(c, bit_cast, BinOpTypeCmpNotEq, trans_create_node_unsigned_negative(c, 0, false));
if_node->data.if_bool_expr.condition = not_eql_zero;
child_scope->node->data.block.statements.append(if_node);

return child_scope->node;
}
}
}

static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *scope, const CallExpr *stmt) {
31 changes: 26 additions & 5 deletions test/translate_c.zig
Original file line number Diff line number Diff line change
@@ -408,15 +408,15 @@ pub fn addCases(cases: &tests.TranslateCContext) {
\\}
,
\\pub export fn s(a: c_int, b: c_int) -> c_int {
\\ var c: c_int;
\\ var c: c_int = undefined;
\\ c = (a + b);
\\ c = (a - b);
\\ c = (a * b);
\\ c = @divTrunc(a, b);
\\ c = @rem(a, b);
\\}
\\pub export fn u(a: c_uint, b: c_uint) -> c_uint {
\\ var c: c_uint;
\\ var c: c_uint = undefined;
\\ c = (a +% b);
\\ c = (a -% b);
\\ c = (a *% b);
@@ -460,7 +460,7 @@ pub fn addCases(cases: &tests.TranslateCContext) {
,
\\pub export fn max(_arg_a: c_int) -> c_int {
\\ var a = _arg_a;
\\ var tmp: c_int;
\\ var tmp: c_int = undefined;
\\ tmp = a;
\\ a = tmp;
\\}
@@ -473,8 +473,8 @@ pub fn addCases(cases: &tests.TranslateCContext) {
\\}
,
\\pub export fn max(a: c_int) {
\\ var b: c_int;
\\ var c: c_int;
\\ var b: c_int = undefined;
\\ var c: c_int = undefined;
\\ c = x: {
\\ const _tmp = a;
\\ b = _tmp;
@@ -1114,4 +1114,25 @@ pub fn addCases(cases: &tests.TranslateCContext) {
,
\\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);
);

cases.add("if on int",
\\int if_int(int i) {
\\ if (i) {
\\ return 0;
\\ } else {
\\ return 1;
\\ }
\\}
,
\\pub fn if_int(i: c_int) -> c_int {
\\ {
\\ const _tmp = i;
\\ if (@bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0) {
\\ return 0;
\\ } else {
\\ return 1;
\\ };
\\ };
\\}
);
}