authorgravatar for evan@lagerdata.comEvan Haas <evan@lagerdata.com> 2021-03-07 20:47:13-08:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-03-17 09:06:47+02:00
log715370a10a1d8cd2b553e6b1b8a328a637707375
tree236486855f464d90aa1ba328ac37bc1e251bccdf
parent4683de1e918c708ded3b111ae43fc702d28b1d52

translate-c: demote usage of un-implemented builtins


4 files changed, 47 insertions(+), 1 deletions(-)

lib/std/c/builtins.zig+6
...@@ -188,3 +188,9 @@ pub fn __builtin_memcpy(...@@ -188,3 +188,9 @@ pub fn __builtin_memcpy(
188pub fn __builtin_expect(expr: c_long, c: c_long) callconv(.Inline) c_long {188pub fn __builtin_expect(expr: c_long, c: c_long) callconv(.Inline) c_long {
189 return expr;189 return expr;
190}190}
191
192// __builtin_alloca_with_align is not currently implemented.
193// It is used in a run-translated-c test and a test-translate-c test to ensure that non-implemented
194// builtins are correctly demoted. If you implement __builtin_alloca_with_align, please update the
195// run-translated-c test and the test-translate-c test to use a different non-implemented builtin.
196// pub fn __builtin_alloca_with_align(size: usize, alignment: usize) callconv(.Inline) *c_void {}
src/translate_c.zig+22-1
...@@ -11,6 +11,7 @@ const math = std.math;...@@ -11,6 +11,7 @@ const math = std.math;
11const ast = @import("translate_c/ast.zig");11const ast = @import("translate_c/ast.zig");
12const Node = ast.Node;12const Node = ast.Node;
13const Tag = Node.Tag;13const Tag = Node.Tag;
14const c_builtins = std.c.builtins;
1415
15const CallingConvention = std.builtin.CallingConvention;16const CallingConvention = std.builtin.CallingConvention;
1617
...@@ -1526,7 +1527,7 @@ fn transImplicitCastExpr(...@@ -1526,7 +1527,7 @@ fn transImplicitCastExpr(
1526 return maybeSuppressResult(c, scope, result_used, ne);1527 return maybeSuppressResult(c, scope, result_used, ne);
1527 },1528 },
1528 .BuiltinFnToFnPtr => {1529 .BuiltinFnToFnPtr => {
1529 return transExpr(c, scope, sub_expr, result_used);1530 return transBuiltinFnExpr(c, scope, sub_expr, result_used);
1530 },1531 },
1531 .ToVoid => {1532 .ToVoid => {
1532 // Should only appear in the rhs and lhs of a ConditionalOperator1533 // Should only appear in the rhs and lhs of a ConditionalOperator
...@@ -1542,6 +1543,22 @@ fn transImplicitCastExpr(...@@ -1542,6 +1543,22 @@ fn transImplicitCastExpr(
1542 }1543 }
1543}1544}
15441545
1546fn isBuiltinDefined(name: []const u8) bool {
1547 inline for (std.meta.declarations(c_builtins)) |decl| {
1548 if (std.mem.eql(u8, name, decl.name)) return true;
1549 }
1550 return false;
1551}
1552
1553fn transBuiltinFnExpr(c: *Context, scope: *Scope, expr: *const clang.Expr, used: ResultUsed) TransError!Node {
1554 const node = try transExpr(c, scope, expr, used);
1555 if (node.castTag(.identifier)) |ident| {
1556 const name = ident.data;
1557 if (!isBuiltinDefined(name)) return fail(c, error.UnsupportedTranslation, expr.getBeginLoc(), "TODO implement function '{s}' in std.c.builtins", .{name});
1558 }
1559 return node;
1560}
1561
1545fn transBoolExpr(1562fn transBoolExpr(
1546 c: *Context,1563 c: *Context,
1547 scope: *Scope,1564 scope: *Scope,
...@@ -4759,6 +4776,10 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!N...@@ -4759,6 +4776,10 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!N
4759 },4776 },
4760 .Identifier => {4777 .Identifier => {
4761 const mangled_name = scope.getAlias(slice);4778 const mangled_name = scope.getAlias(slice);
4779 if (mem.startsWith(u8, mangled_name, "__builtin_") and !isBuiltinDefined(mangled_name)) {
4780 try m.fail(c, "TODO implement function '{s}' in std.c.builtins", .{mangled_name});
4781 return error.ParseError;
4782 }
4762 return Tag.identifier.create(c.arena, builtin_typedef_map.get(mangled_name) orelse mangled_name);4783 return Tag.identifier.create(c.arena, builtin_typedef_map.get(mangled_name) orelse mangled_name);
4763 },4784 },
4764 .LParen => {4785 .LParen => {
test/run_translated_c.zig+12
...@@ -1221,4 +1221,16 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {...@@ -1221,4 +1221,16 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {
1221 \\ return 0;1221 \\ return 0;
1222 \\}1222 \\}
1223 , "");1223 , "");
1224
1225 // See __builtin_alloca_with_align comment in std.c.builtins
1226 cases.add("use of unimplemented builtin in unused function does not prevent compilation",
1227 \\#include <stdlib.h>
1228 \\void unused() {
1229 \\ __builtin_alloca_with_align(1, 8);
1230 \\}
1231 \\int main(void) {
1232 \\ if (__builtin_sqrt(1.0) != 1.0) abort();
1233 \\ return 0;
1234 \\}
1235 , "");
1224}1236}
test/translate_c.zig+7
...@@ -3418,4 +3418,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -3418,4 +3418,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
3418 \\pub const MAY_NEED_PROMOTION_HEX = @import("std").meta.promoteIntLiteral(c_int, 0x80000000, .hexadecimal);3418 \\pub const MAY_NEED_PROMOTION_HEX = @import("std").meta.promoteIntLiteral(c_int, 0x80000000, .hexadecimal);
3419 \\pub const MAY_NEED_PROMOTION_OCT = @import("std").meta.promoteIntLiteral(c_int, 0o20000000000, .octal);3419 \\pub const MAY_NEED_PROMOTION_OCT = @import("std").meta.promoteIntLiteral(c_int, 0o20000000000, .octal);
3420 });3420 });
3421
3422 // See __builtin_alloca_with_align comment in std.c.builtins
3423 cases.add("demote un-implemented builtins",
3424 \\#define FOO(X) __builtin_alloca_with_align((X), 8)
3425 , &[_][]const u8{
3426 \\pub const FOO = @compileError("TODO implement function '__builtin_alloca_with_align' in std.c.builtins");
3427 });
3421}3428}