| author | |
| committer | |
| log | a3624e94f812efaae40d2ca66da0b49ca63cb936 |
| tree | 0b61ed0ac590fd166472864335dac8a659e730ba |
| parent | 29fd0c6d61d1569c1691fc5489d51311207b1759 |
| signature |
2 files changed, 43 insertions(+), 4 deletions(-)
lib/std/meta.zig+31| ... | @@ -795,3 +795,34 @@ test "std.meta.cast" { | ... | @@ -795,3 +795,34 @@ test "std.meta.cast" { |
| 795 | testing.expectEqual(@as(u32, 10), cast(u32, @as(u64, 10))); | 795 | testing.expectEqual(@as(u32, 10), cast(u32, @as(u64, 10))); |
| 796 | testing.expectEqual(@as(u8, 2), cast(u8, E.Two)); | 796 | testing.expectEqual(@as(u8, 2), cast(u8, E.Two)); |
| 797 | } | 797 | } |
| 798 | |||
| 799 | /// Given a value returns its size as C's sizeof operator would. | ||
| 800 | /// This is for translate-c and is not intended for general use. | ||
| 801 | pub fn sizeof(target: anytype) usize { | ||
| 802 | switch (@typeInfo(@TypeOf(target))) { | ||
| 803 | .Type => return @sizeOf(target), | ||
| 804 | .Float, .Int, .Struct, .Union, .Enum => return @sizeOf(@TypeOf(target)), | ||
| 805 | .ComptimeFloat => return @sizeOf(f64), // TODO c_double #3999 | ||
| 806 | .ComptimeInt => { | ||
| 807 | // TODO to get the correct result we have to translate | ||
| 808 | // `1073741824 * 4` as `int(1073741824) *% int(4)` since | ||
| 809 | // sizeof(1073741824 * 4) != sizeof(4294967296). | ||
| 810 | |||
| 811 | // TODO test if target fits in int, long or long long | ||
| 812 | return @sizeOf(c_int); | ||
| 813 | }, | ||
| 814 | else => @compileError("TODO implement std.meta.sizeof for type " ++ @typeName(@TypeOf(target))), | ||
| 815 | } | ||
| 816 | } | ||
| 817 | |||
| 818 | test "sizeof" { | ||
| 819 | const E = extern enum(c_int) { One, _ }; | ||
| 820 | const S = extern struct { a: u32 }; | ||
| 821 | |||
| 822 | testing.expect(sizeof(u32) == 4); | ||
| 823 | testing.expect(sizeof(@as(u32, 2)) == 4); | ||
| 824 | testing.expect(sizeof(2) == @sizeOf(c_int)); | ||
| 825 | testing.expect(sizeof(E) == @sizeOf(c_int)); | ||
| 826 | testing.expect(sizeof(E.One) == @sizeOf(c_int)); | ||
| 827 | testing.expect(sizeof(S) == 4); | ||
| 828 | } |
src-self-hosted/translate_c.zig+12-4| ... | @@ -6324,10 +6324,18 @@ fn parseCPrefixOpExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast. | ... | @@ -6324,10 +6324,18 @@ fn parseCPrefixOpExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast. |
| 6324 | break :blk inner; | 6324 | break :blk inner; |
| 6325 | } else try parseCPrefixOpExpr(c, m, scope); | 6325 | } else try parseCPrefixOpExpr(c, m, scope); |
| 6326 | 6326 | ||
| 6327 | const builtin_call = try c.createBuiltinCall("@sizeOf", 1); | 6327 | //(@import("std").meta.sizeof(dest, x)) |
| 6328 | builtin_call.params()[0] = inner; | 6328 | const import_fn_call = try c.createBuiltinCall("@import", 1); |
| 6329 | builtin_call.rparen_token = try appendToken(c, .RParen, ")"); | 6329 | const std_node = try transCreateNodeStringLiteral(c, "\"std\""); |
| 6330 | return &builtin_call.base; | 6330 | import_fn_call.params()[0] = std_node; |
| 6331 | import_fn_call.rparen_token = try appendToken(c, .RParen, ")"); | ||
| 6332 | const inner_field_access = try transCreateNodeFieldAccess(c, &import_fn_call.base, "meta"); | ||
| 6333 | const outer_field_access = try transCreateNodeFieldAccess(c, inner_field_access, "sizeof"); | ||
| 6334 | |||
| 6335 | const sizeof_call = try c.createCall(outer_field_access, 1); | ||
| 6336 | sizeof_call.params()[0] = inner; | ||
| 6337 | sizeof_call.rtoken = try appendToken(c, .RParen, ")"); | ||
| 6338 | return &sizeof_call.base; | ||
| 6331 | }, | 6339 | }, |
| 6332 | .Keyword_alignof => { | 6340 | .Keyword_alignof => { |
| 6333 | // TODO this won't work if using <stdalign.h>'s | 6341 | // TODO this won't work if using <stdalign.h>'s |