authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-02-16 16:34:37+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-02-16 16:40:43+02:00
log9a826ccbe0b10046e5dd7c482e9e87912c0fa95c
tree4bc4ca5c768e52ce457d27e8c193b3cdd3c4b7c4
parent74e9d4ca820f9940b47ae658c41e7edb315681c8
signature Commit is signed but in an unrecognized format.

translate-c: elide some unecessary casts of literals


5 files changed, 104 insertions(+), 54 deletions(-)

src/clang.zig+4-1
......@@ -127,6 +127,9 @@ pub const APSInt = opaque {
127127
128128 pub const getNumWords = ZigClangAPSInt_getNumWords;
129129 extern fn ZigClangAPSInt_getNumWords(*const APSInt) c_uint;
130
131 pub const lessThanEqual = ZigClangAPSInt_lessThanEqual;
132 extern fn ZigClangAPSInt_lessThanEqual(*const APSInt, rhs: u64) bool;
130133};
131134
132135pub const ASTContext = opaque {
......@@ -407,7 +410,7 @@ pub const Expr = opaque {
407410 pub const getBeginLoc = ZigClangExpr_getBeginLoc;
408411 extern fn ZigClangExpr_getBeginLoc(*const Expr) SourceLocation;
409412
410 pub const EvaluateAsConstantExpr = ZigClangExpr_EvaluateAsConstantExpr;
413 pub const evaluateAsConstantExpr = ZigClangExpr_EvaluateAsConstantExpr;
411414 extern fn ZigClangExpr_EvaluateAsConstantExpr(*const Expr, *ExprEvalResult, Expr_ConstExprUsage, *const ASTContext) bool;
412415};
413416
src/translate_c.zig+47-5
......@@ -1820,11 +1820,55 @@ fn transExprCoercing(c: *Context, scope: *Scope, expr: *const clang.Expr, used:
18201820 return transExprCoercing(c, scope, un_expr.getSubExpr(), used);
18211821 }
18221822 },
1823 .ImplicitCastExprClass => {
1824 const cast_expr = @ptrCast(*const clang.ImplicitCastExpr, expr);
1825 const sub_expr = cast_expr.getSubExpr();
1826 switch (@ptrCast(*const clang.Stmt, sub_expr).getStmtClass()) {
1827 .IntegerLiteralClass, .CharacterLiteralClass => switch (cast_expr.getCastKind()) {
1828 .IntegralToFloating => return transExprCoercing(c, scope, sub_expr, used),
1829 .IntegralCast => {
1830 const dest_type = getExprQualType(c, expr);
1831 if (literalFitsInType(c, sub_expr, dest_type))
1832 return transExprCoercing(c, scope, sub_expr, used);
1833 },
1834 else => {},
1835 },
1836 else => {},
1837 }
1838 },
18231839 else => {},
18241840 }
18251841 return transExpr(c, scope, expr, .used);
18261842}
18271843
1844fn literalFitsInType(c: *Context, expr: *const clang.Expr, qt: clang.QualType) bool {
1845 var width = qualTypeIntBitWidth(c, qt) catch 8;
1846 if (width == 0) width = 8; // Byte is the smallest type.
1847 const is_signed = cIsSignedInteger(qt);
1848 const width_max_int= (@as(u64, 1) << math.lossyCast(u6, width - @boolToInt(is_signed))) - 1;
1849
1850 switch (@ptrCast(*const clang.Stmt, expr).getStmtClass()) {
1851 .CharacterLiteralClass => {
1852 const char_lit = @ptrCast(*const clang.CharacterLiteral, expr);
1853 const val = char_lit.getValue();
1854 // If the val is less than the max int then it fits.
1855 return val <= width_max_int;
1856 },
1857 .IntegerLiteralClass => {
1858 const int_lit = @ptrCast(*const clang.IntegerLiteral, expr);
1859 var eval_result: clang.ExprEvalResult = undefined;
1860 if (!int_lit.EvaluateAsInt(&eval_result, c.clang_context)) {
1861 return false;
1862 }
1863
1864 const int = eval_result.Val.getInt();
1865 return int.lessThanEqual(width_max_int);
1866 },
1867 else => unreachable,
1868 }
1869
1870}
1871
18281872fn transInitListExprRecord(
18291873 c: *Context,
18301874 scope: *Scope,
......@@ -2331,7 +2375,7 @@ fn transDefault(
23312375
23322376fn transConstantExpr(c: *Context, scope: *Scope, expr: *const clang.Expr, used: ResultUsed) TransError!Node {
23332377 var result: clang.ExprEvalResult = undefined;
2334 if (!expr.EvaluateAsConstantExpr(&result, .EvaluateForCodeGen, c.clang_context))
2378 if (!expr.evaluateAsConstantExpr(&result, .EvaluateForCodeGen, c.clang_context))
23352379 return fail(c, error.UnsupportedTranslation, expr.getBeginLoc(), "invalid constant expression", .{});
23362380
23372381 switch (result.Val.getKind()) {
......@@ -3171,7 +3215,7 @@ fn qualTypeIsBoolean(qt: clang.QualType) bool {
31713215 return qualTypeCanon(qt).isBooleanType();
31723216}
31733217
3174fn qualTypeIntBitWidth(c: *Context, qt: clang.QualType, source_loc: clang.SourceLocation) !u32 {
3218fn qualTypeIntBitWidth(c: *Context, qt: clang.QualType) !u32 {
31753219 const ty = qt.getTypePtr();
31763220
31773221 switch (ty.getTypeClass()) {
......@@ -3211,12 +3255,10 @@ fn qualTypeIntBitWidth(c: *Context, qt: clang.QualType, source_loc: clang.Source
32113255 },
32123256 else => return 0,
32133257 }
3214
3215 unreachable;
32163258}
32173259
32183260fn qualTypeToLog2IntRef(c: *Context, qt: clang.QualType, source_loc: clang.SourceLocation) !Node {
3219 const int_bit_width = try qualTypeIntBitWidth(c, qt, source_loc);
3261 const int_bit_width = try qualTypeIntBitWidth(c, qt);
32203262
32213263 if (int_bit_width != 0) {
32223264 // we can perform the log2 now.
src/zig_clang.cpp+5
......@@ -2244,6 +2244,11 @@ unsigned ZigClangAPSInt_getNumWords(const ZigClangAPSInt *self) {
22442244 return casted->getNumWords();
22452245}
22462246
2247bool ZigClangAPSInt_lessThanEqual(const ZigClangAPSInt *self, uint64_t rhs) {
2248 auto casted = reinterpret_cast<const llvm::APSInt *>(self);
2249 return casted->ule(rhs);
2250}
2251
22472252uint64_t ZigClangAPInt_getLimitedValue(const ZigClangAPInt *self, uint64_t limit) {
22482253 auto casted = reinterpret_cast<const llvm::APInt *>(self);
22492254 return casted->getLimitedValue(limit);
src/zig_clang.h+1
......@@ -1097,6 +1097,7 @@ ZIG_EXTERN_C const struct ZigClangAPSInt *ZigClangAPSInt_negate(const struct Zig
10971097ZIG_EXTERN_C void ZigClangAPSInt_free(const struct ZigClangAPSInt *self);
10981098ZIG_EXTERN_C const uint64_t *ZigClangAPSInt_getRawData(const struct ZigClangAPSInt *self);
10991099ZIG_EXTERN_C unsigned ZigClangAPSInt_getNumWords(const struct ZigClangAPSInt *self);
1100ZIG_EXTERN_C bool ZigClangAPSInt_lessThanEqual(const struct ZigClangAPSInt *self, uint64_t rhs);
11001101
11011102ZIG_EXTERN_C uint64_t ZigClangAPInt_getLimitedValue(const struct ZigClangAPInt *self, uint64_t limit);
11021103
test/translate_c.zig+47-48
......@@ -313,22 +313,22 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
313313 , &[_][]const u8{
314314 \\pub const uuid_t = [16]u8;
315315 \\pub const UUID_NULL: uuid_t = [16]u8{
316 \\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
317 \\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
318 \\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
319 \\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
320 \\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
321 \\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
322 \\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
323 \\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
324 \\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
325 \\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
326 \\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
327 \\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
328 \\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
329 \\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
330 \\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
331 \\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
316 \\ 0,
317 \\ 0,
318 \\ 0,
319 \\ 0,
320 \\ 0,
321 \\ 0,
322 \\ 0,
323 \\ 0,
324 \\ 0,
325 \\ 0,
326 \\ 0,
327 \\ 0,
328 \\ 0,
329 \\ 0,
330 \\ 0,
331 \\ 0,
332332 \\};
333333 });
334334
......@@ -382,10 +382,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
382382 \\};
383383 \\pub export var ub: union_unnamed_1 = union_unnamed_1{
384384 \\ .c = [4]u8{
385 \\ @bitCast(u8, @truncate(i8, @as(c_int, 'a'))),
386 \\ @bitCast(u8, @truncate(i8, @as(c_int, 'b'))),
387 \\ @bitCast(u8, @truncate(i8, @as(c_int, 'b'))),
388 \\ @bitCast(u8, @truncate(i8, @as(c_int, 'a'))),
385 \\ 'a',
386 \\ 'b',
387 \\ 'b',
388 \\ 'a',
389389 \\ },
390390 \\};
391391 });
......@@ -512,7 +512,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
512512 , &[_][]const u8{
513513 \\pub export fn foo() void {
514514 \\ var a: c_int = undefined;
515 \\ var b: u8 = @bitCast(u8, @truncate(i8, @as(c_int, 123)));
515 \\ var b: u8 = 123;
516516 \\ const c: c_int = undefined;
517517 \\ const d: c_uint = @bitCast(c_uint, @as(c_int, 440));
518518 \\ var e: c_int = 10;
......@@ -1468,7 +1468,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
14681468 , &[_][]const u8{
14691469 \\pub fn foo() callconv(.C) void {
14701470 \\ var arr: [10]u8 = [1]u8{
1471 \\ @bitCast(u8, @truncate(i8, @as(c_int, 1))),
1471 \\ 1,
14721472 \\ } ++ [1]u8{0} ** 9;
14731473 \\ var arr1: [10][*c]u8 = [1][*c]u8{
14741474 \\ null,
......@@ -1721,13 +1721,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
17211721 \\ unsigned d = 440;
17221722 \\}
17231723 , &[_][]const u8{
1724 \\pub var a: c_long = @bitCast(c_long, @as(c_long, @as(c_int, 2)));
1725 \\pub var b: c_long = @bitCast(c_long, @as(c_long, @as(c_int, 2)));
1724 \\pub var a: c_long = 2;
1725 \\pub var b: c_long = 2;
17261726 \\pub var c: c_int = 4;
17271727 \\pub export fn foo(arg_c_1: u8) void {
17281728 \\ var c_1 = arg_c_1;
17291729 \\ var a_2: c_int = undefined;
1730 \\ var b_3: u8 = @bitCast(u8, @truncate(i8, @as(c_int, 123)));
1730 \\ var b_3: u8 = 123;
17311731 \\ b_3 = @bitCast(u8, @truncate(i8, a_2));
17321732 \\ {
17331733 \\ var d: c_int = 5;
......@@ -1838,7 +1838,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
18381838 \\ };
18391839 \\ }
18401840 \\ }
1841 \\ var i: u8 = @bitCast(u8, @truncate(i8, @as(c_int, 2)));
1841 \\ var i: u8 = 2;
18421842 \\}
18431843 });
18441844
......@@ -1846,7 +1846,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
18461846 \\unsigned anyerror = 2;
18471847 \\#define noreturn _Noreturn
18481848 , &[_][]const u8{
1849 \\pub export var anyerror_1: c_uint = @bitCast(c_uint, @as(c_int, 2));
1849 \\pub export var anyerror_1: c_uint = 2;
18501850 ,
18511851 \\pub const noreturn_2 = @compileError("unable to translate C expr: unexpected token .Keyword_noreturn");
18521852 });
......@@ -1860,7 +1860,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
18601860 \\pub export var a: f32 = @floatCast(f32, 3.1415);
18611861 \\pub export var b: f64 = 3.1415;
18621862 \\pub export var c: c_int = @floatToInt(c_int, 3.1415);
1863 \\pub export var d: f64 = @intToFloat(f64, @as(c_int, 3));
1863 \\pub export var d: f64 = 3;
18641864 });
18651865
18661866 cases.add("conditional operator",
......@@ -2009,7 +2009,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
20092009 \\}
20102010 });
20112011
2012 // TODO translate-c should in theory be able to figure out to drop all these casts
20132012 cases.add("escape sequences",
20142013 \\const char *escapes() {
20152014 \\char a = '\'',
......@@ -2028,17 +2027,17 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
20282027 \\
20292028 , &[_][]const u8{
20302029 \\pub export fn escapes() [*c]const u8 {
2031 \\ var a: u8 = @bitCast(u8, @truncate(i8, @as(c_int, '\'')));
2032 \\ var b: u8 = @bitCast(u8, @truncate(i8, @as(c_int, '\\')));
2033 \\ var c: u8 = @bitCast(u8, @truncate(i8, @as(c_int, '\x07')));
2034 \\ var d: u8 = @bitCast(u8, @truncate(i8, @as(c_int, '\x08')));
2035 \\ var e: u8 = @bitCast(u8, @truncate(i8, @as(c_int, '\x0c')));
2036 \\ var f: u8 = @bitCast(u8, @truncate(i8, @as(c_int, '\n')));
2037 \\ var g: u8 = @bitCast(u8, @truncate(i8, @as(c_int, '\r')));
2038 \\ var h: u8 = @bitCast(u8, @truncate(i8, @as(c_int, '\t')));
2039 \\ var i: u8 = @bitCast(u8, @truncate(i8, @as(c_int, '\x0b')));
2040 \\ var j: u8 = @bitCast(u8, @truncate(i8, @as(c_int, '\x00')));
2041 \\ var k: u8 = @bitCast(u8, @truncate(i8, @as(c_int, '\"')));
2030 \\ var a: u8 = '\'';
2031 \\ var b: u8 = '\\';
2032 \\ var c: u8 = '\x07';
2033 \\ var d: u8 = '\x08';
2034 \\ var e: u8 = '\x0c';
2035 \\ var f: u8 = '\n';
2036 \\ var g: u8 = '\r';
2037 \\ var h: u8 = '\t';
2038 \\ var i: u8 = '\x0b';
2039 \\ var j: u8 = '\x00';
2040 \\ var k: u8 = '\"';
20422041 \\ return "\'\\\x07\x08\x0c\n\r\t\x0b\x00\"";
20432042 \\}
20442043 });
......@@ -2308,8 +2307,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
23082307 , &[_][]const u8{
23092308 \\pub export fn foo() void {
23102309 \\ var a: [10]c_longlong = undefined;
2311 \\ var i: c_longlong = @bitCast(c_longlong, @as(c_longlong, @as(c_int, 0)));
2312 \\ a[@intCast(usize, i)] = @bitCast(c_longlong, @as(c_longlong, @as(c_int, 0)));
2310 \\ var i: c_longlong = 0;
2311 \\ a[@intCast(usize, i)] = 0;
23132312 \\}
23142313 });
23152314
......@@ -2321,8 +2320,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
23212320 , &[_][]const u8{
23222321 \\pub export fn foo() void {
23232322 \\ var a: [10]c_uint = undefined;
2324 \\ var i: c_uint = @bitCast(c_uint, @as(c_int, 0));
2325 \\ a[i] = @bitCast(c_uint, @as(c_int, 0));
2323 \\ var i: c_uint = 0;
2324 \\ a[i] = 0;
23262325 \\}
23272326 });
23282327
......@@ -2527,7 +2526,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
25272526 , &[_][]const u8{
25282527 \\pub export fn foo() void {
25292528 \\ var i: c_int = 0;
2530 \\ var u: c_uint = @bitCast(c_uint, @as(c_int, 0));
2529 \\ var u: c_uint = 0;
25312530 \\ i += 1;
25322531 \\ i -= 1;
25332532 \\ u +%= 1;
......@@ -2614,7 +2613,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
26142613 , &[_][]const u8{
26152614 \\pub export fn foo() void {
26162615 \\ var a: c_int = 0;
2617 \\ var b: c_uint = @bitCast(c_uint, @as(c_int, 0));
2616 \\ var b: c_uint = 0;
26182617 \\ a += blk: {
26192618 \\ const ref = &a;
26202619 \\ ref.* += @as(c_int, 1);
......@@ -2692,7 +2691,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
26922691 \\}
26932692 , &[_][]const u8{
26942693 \\pub export fn foo() void {
2695 \\ var a: c_uint = @bitCast(c_uint, @as(c_int, 0));
2694 \\ var a: c_uint = 0;
26962695 \\ a +%= blk: {
26972696 \\ const ref = &a;
26982697 \\ ref.* +%= @bitCast(c_uint, @as(c_int, 1));
......@@ -2752,7 +2751,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
27522751 , &[_][]const u8{
27532752 \\pub export fn foo() void {
27542753 \\ var i: c_int = 0;
2755 \\ var u: c_uint = @bitCast(c_uint, @as(c_int, 0));
2754 \\ var u: c_uint = 0;
27562755 \\ i += 1;
27572756 \\ i -= 1;
27582757 \\ u +%= 1;