Commit a3624e94f8

Vexu <git@vexu.eu>
2020-09-14 22:53:38
translate-c: determine sizeof using std.meta.sizeof
1 parent 29fd0c6
Changed files (2)
lib
src-self-hosted
lib/std/meta.zig
@@ -795,3 +795,34 @@ test "std.meta.cast" {
     testing.expectEqual(@as(u32, 10), cast(u32, @as(u64, 10)));
     testing.expectEqual(@as(u8, 2), cast(u8, E.Two));
 }
+
+/// Given a value returns its size as C's sizeof operator would.
+/// This is for translate-c and is not intended for general use.
+pub fn sizeof(target: anytype) usize {
+    switch (@typeInfo(@TypeOf(target))) {
+        .Type => return @sizeOf(target),
+        .Float, .Int, .Struct, .Union, .Enum => return @sizeOf(@TypeOf(target)),
+        .ComptimeFloat => return @sizeOf(f64), // TODO c_double #3999
+        .ComptimeInt => {
+            // TODO to get the correct result we have to translate
+            // `1073741824 * 4` as `int(1073741824) *% int(4)` since
+            // sizeof(1073741824 * 4) != sizeof(4294967296).
+            
+            // TODO test if target fits in int, long or long long
+            return @sizeOf(c_int);
+        },
+        else => @compileError("TODO implement std.meta.sizeof for type " ++ @typeName(@TypeOf(target))),
+    }
+}
+
+test "sizeof" {
+    const E = extern enum(c_int) { One, _ };
+    const S = extern struct { a: u32 };
+
+    testing.expect(sizeof(u32) == 4);
+    testing.expect(sizeof(@as(u32, 2)) == 4);
+    testing.expect(sizeof(2) == @sizeOf(c_int));
+    testing.expect(sizeof(E) == @sizeOf(c_int));
+    testing.expect(sizeof(E.One) == @sizeOf(c_int));
+    testing.expect(sizeof(S) == 4);
+}
src-self-hosted/translate_c.zig
@@ -6324,10 +6324,18 @@ fn parseCPrefixOpExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.
                 break :blk inner;
             } else try parseCPrefixOpExpr(c, m, scope);
 
-            const builtin_call = try c.createBuiltinCall("@sizeOf", 1);
-            builtin_call.params()[0] = inner;
-            builtin_call.rparen_token = try appendToken(c, .RParen, ")");
-            return &builtin_call.base;
+            //(@import("std").meta.sizeof(dest, x))
+            const import_fn_call = try c.createBuiltinCall("@import", 1);
+            const std_node = try transCreateNodeStringLiteral(c, "\"std\"");
+            import_fn_call.params()[0] = std_node;
+            import_fn_call.rparen_token = try appendToken(c, .RParen, ")");
+            const inner_field_access = try transCreateNodeFieldAccess(c, &import_fn_call.base, "meta");
+            const outer_field_access = try transCreateNodeFieldAccess(c, inner_field_access, "sizeof");
+
+            const sizeof_call = try c.createCall(outer_field_access, 1);
+            sizeof_call.params()[0] = inner;
+            sizeof_call.rtoken = try appendToken(c, .RParen, ")");
+            return &sizeof_call.base;
         },
         .Keyword_alignof => {
             // TODO this won't work if using <stdalign.h>'s