Skip to content

Commit 259e1be

Browse files
committed
translate-c: elide some unecessary casts of literals
1 parent 3fbe4f5 commit 259e1be

File tree

5 files changed

+104
-54
lines changed

5 files changed

+104
-54
lines changed

src/clang.zig

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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

132135
pub 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

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -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

1844+
fn 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+
18281872
fn transInitListExprRecord(
18291873
c: *Context,
18301874
scope: *Scope,
@@ -2331,7 +2375,7 @@ fn transDefault(
23312375

23322376
fn 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

3174-
fn qualTypeIntBitWidth(c: *Context, qt: clang.QualType, source_loc: clang.SourceLocation) !u32 {
3218+
fn 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

32183260
fn 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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2244,6 +2244,11 @@ unsigned ZigClangAPSInt_getNumWords(const ZigClangAPSInt *self) {
22442244
return casted->getNumWords();
22452245
}
22462246

2247+
bool ZigClangAPSInt_lessThanEqual(const ZigClangAPSInt *self, uint64_t rhs) {
2248+
auto casted = reinterpret_cast<const llvm::APSInt *>(self);
2249+
return casted->ule(rhs);
2250+
}
2251+
22472252
uint64_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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1097,6 +1097,7 @@ ZIG_EXTERN_C const struct ZigClangAPSInt *ZigClangAPSInt_negate(const struct Zig
10971097
ZIG_EXTERN_C void ZigClangAPSInt_free(const struct ZigClangAPSInt *self);
10981098
ZIG_EXTERN_C const uint64_t *ZigClangAPSInt_getRawData(const struct ZigClangAPSInt *self);
10991099
ZIG_EXTERN_C unsigned ZigClangAPSInt_getNumWords(const struct ZigClangAPSInt *self);
1100+
ZIG_EXTERN_C bool ZigClangAPSInt_lessThanEqual(const struct ZigClangAPSInt *self, uint64_t rhs);
11001101

11011102
ZIG_EXTERN_C uint64_t ZigClangAPInt_getLimitedValue(const struct ZigClangAPInt *self, uint64_t limit);
11021103

test/translate_c.zig

Lines changed: 47 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -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,15 +1838,15 @@ 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

18451845
cases.add("shadowing primitive types",
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;

0 commit comments

Comments
 (0)