authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-03-06 10:43:52-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2018-03-06 10:43:52-05:00
log46e258c9f76cee5b37042913c34b3a1a07cce0a6
tree7616fa2cb13df1f69b5865e9df99ac30dcd7b2fd
parentc3807dfb34e3d0696517f3adf1f10ed096bd5fc3
parent1d378d8f261603dde69055646b1806ada393b1e0
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #815 from Hejsil/more-translate-c

Translate C now handles bools better

2 files changed, 153 insertions(+), 80 deletions(-)

src/translate_c.cpp+81-70
...@@ -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,
118static TransScope *trans_stmt(Context *c, TransScope *scope, const Stmt *stmt, AstNode **out_node);118static TransScope *trans_stmt(Context *c, TransScope *scope, const Stmt *stmt, AstNode **out_node);
119static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const Expr *expr, TransLRValue lrval);119static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const Expr *expr, TransLRValue lrval);
120static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc);120static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc);
121121static AstNode *trans_to_bool_expr(Context *c, TransScope *scope, AstNode *expr);
122122
123ATTRIBUTE_PRINTF(3, 4)123ATTRIBUTE_PRINTF(3, 4)
124static void emit_warning(Context *c, const SourceLocation &sl, const char *format, ...) {124static 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 *_ref1390 // 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}
21992205
2200static AstNode *trans_while_loop(Context *c, TransScope *scope, const WhileStmt *stmt) {2206static 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
2215static 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 }
22502222
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 }
22592230
2260 case NodeTypeBoolLiteral:2231 case NodeTypeBoolLiteral:
2261 if_node->data.if_bool_expr.condition = condition_node;2232 return expr;
2262 return if_node;
22632233
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 size2236 // To make it work, we bitcast any value we get to an int of the right size
2267 // and comp it to 02237 // and comp it to 0
2268 // TODO: This doesn't work for pointers, as they become nullable on2238 // TODO: This doesn't work for pointers, as they become nullable on
2269 // translate2239 // 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;
22772249
2278 // const _tmp = cond;2250 // const _tmp = cond;
2279 // TODO: avoid name collisions with generated variable names2251 // 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);
22832255
2284 // @sizeOf(@typeOf(_tmp)) * 82256 // @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));
22922264
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));
23022274
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);
23072278
2308 return child_scope->node;2279 return child_scope->node;
2309 }2280 }
2310 }2281 }
2311}2282}
23122283
2284static 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
2299static 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
2313static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *scope, const CallExpr *stmt) {2322static 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);
23152324
...@@ -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 }
25002511
2501 const Stmt *inc_stmt = stmt->getInc();2512 const Stmt *inc_stmt = stmt->getInc();
test/translate_c.zig+72-10
...@@ -1083,6 +1083,21 @@ pub fn addCases(cases: &tests.TranslateCContext) void {...@@ -1083,6 +1083,21 @@ pub fn addCases(cases: &tests.TranslateCContext) void {
1083 \\}1083 \\}
1084 );1084 );
10851085
1086 cases.add("bool not",
1087 \\int foo(int x) {
1088 \\ return !(x == 0);
1089 \\ return !x;
1090 \\}
1091 ,
1092 \\pub fn foo(x: c_int) c_int {
1093 \\ return !(x == 0);
1094 \\ return !__to_bool_expr: {
1095 \\ const _tmp = x;
1096 \\ break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0;
1097 \\ };
1098 \\}
1099 );
1100
1086 cases.add("primitive types included in defined symbols",1101 cases.add("primitive types included in defined symbols",
1087 \\int foo(int u32) {1102 \\int foo(int u32) {
1088 \\ return u32;1103 \\ return u32;
...@@ -1110,7 +1125,7 @@ pub fn addCases(cases: &tests.TranslateCContext) void {...@@ -1110,7 +1125,7 @@ pub fn addCases(cases: &tests.TranslateCContext) void {
1110 );1125 );
11111126
1112 cases.add("macro pointer cast",1127 cases.add("macro pointer cast",
1113 \\#define NRF_GPIO ((NRF_GPIO_Type *) NRF_GPIO_BASE) 1128 \\#define NRF_GPIO ((NRF_GPIO_Type *) NRF_GPIO_BASE)
1114 ,1129 ,
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);1130 \\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 );1131 );
...@@ -1124,15 +1139,62 @@ pub fn addCases(cases: &tests.TranslateCContext) void {...@@ -1124,15 +1139,62 @@ pub fn addCases(cases: &tests.TranslateCContext) void {
1124 \\ }1139 \\ }
1125 \\}1140 \\}
1126 ,1141 ,
1127 \\pub fn if_int(i: c_int) c_int {1142 \\pub fn if_int(i: c_int) c_int {
1128 \\ {1143 \\ if (__to_bool_expr: {
1129 \\ const _tmp = i;1144 \\ const _tmp = i;
1130 \\ if (@bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0) {1145 \\ break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0;
1131 \\ return 0;1146 \\ }) {
1132 \\ } else {1147 \\ return 0;
1133 \\ return 1;1148 \\ } else {
1134 \\ };1149 \\ return 1;
1135 \\ };1150 \\ };
1151 \\}
1152 );
1153
1154 cases.add("while on int",
1155 \\int while_int(int i) {
1156 \\ while (i) {
1157 \\ return 0;
1158 \\ }
1159 \\}
1160 ,
1161 \\pub fn while_int(i: c_int) c_int {
1162 \\ while (__to_bool_expr: {
1163 \\ const _tmp = i;
1164 \\ break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0;
1165 \\ }) {
1166 \\ return 0;
1167 \\ };
1168 \\}
1169 );
1170
1171 cases.add("for on int",
1172 \\int for_int(int i) {
1173 \\ for (;i;) {
1174 \\ return 0;
1175 \\ }
1176 \\
1177 \\ for (int j = 4;j;j--) {
1178 \\ return 0;
1179 \\ }
1136 \\}1180 \\}
1181 ,
1182 \\pub fn for_int(i: c_int) c_int {
1183 \\ while (__to_bool_expr: {
1184 \\ const _tmp = i;
1185 \\ break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0;
1186 \\ }) {
1187 \\ return 0;
1188 \\ };
1189 \\ {
1190 \\ var j: c_int = 4;
1191 \\ while (__to_bool_expr: {
1192 \\ const _tmp = j;
1193 \\ break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0;
1194 \\ }) : (j -= 1) {
1195 \\ return 0;
1196 \\ };
1197 \\ };
1198 \\}
1137 );1199 );
1138}1200}