translate-c: elide some unecessary casts of literals

This commit is contained in:
Veikka Tuominen 2021-02-16 16:34:37 +02:00
parent 74e9d4ca82
commit 9a826ccbe0
No known key found for this signature in database
GPG Key ID: 59AEB8936E16A6AC
5 changed files with 104 additions and 54 deletions

View File

@ -127,6 +127,9 @@ pub const APSInt = opaque {
pub const getNumWords = ZigClangAPSInt_getNumWords;
extern fn ZigClangAPSInt_getNumWords(*const APSInt) c_uint;
pub const lessThanEqual = ZigClangAPSInt_lessThanEqual;
extern fn ZigClangAPSInt_lessThanEqual(*const APSInt, rhs: u64) bool;
};
pub const ASTContext = opaque {
@ -407,7 +410,7 @@ pub const Expr = opaque {
pub const getBeginLoc = ZigClangExpr_getBeginLoc;
extern fn ZigClangExpr_getBeginLoc(*const Expr) SourceLocation;
pub const EvaluateAsConstantExpr = ZigClangExpr_EvaluateAsConstantExpr;
pub const evaluateAsConstantExpr = ZigClangExpr_EvaluateAsConstantExpr;
extern fn ZigClangExpr_EvaluateAsConstantExpr(*const Expr, *ExprEvalResult, Expr_ConstExprUsage, *const ASTContext) bool;
};

View File

@ -1820,11 +1820,55 @@ fn transExprCoercing(c: *Context, scope: *Scope, expr: *const clang.Expr, used:
return transExprCoercing(c, scope, un_expr.getSubExpr(), used);
}
},
.ImplicitCastExprClass => {
const cast_expr = @ptrCast(*const clang.ImplicitCastExpr, expr);
const sub_expr = cast_expr.getSubExpr();
switch (@ptrCast(*const clang.Stmt, sub_expr).getStmtClass()) {
.IntegerLiteralClass, .CharacterLiteralClass => switch (cast_expr.getCastKind()) {
.IntegralToFloating => return transExprCoercing(c, scope, sub_expr, used),
.IntegralCast => {
const dest_type = getExprQualType(c, expr);
if (literalFitsInType(c, sub_expr, dest_type))
return transExprCoercing(c, scope, sub_expr, used);
},
else => {},
},
else => {},
}
},
else => {},
}
return transExpr(c, scope, expr, .used);
}
fn literalFitsInType(c: *Context, expr: *const clang.Expr, qt: clang.QualType) bool {
var width = qualTypeIntBitWidth(c, qt) catch 8;
if (width == 0) width = 8; // Byte is the smallest type.
const is_signed = cIsSignedInteger(qt);
const width_max_int= (@as(u64, 1) << math.lossyCast(u6, width - @boolToInt(is_signed))) - 1;
switch (@ptrCast(*const clang.Stmt, expr).getStmtClass()) {
.CharacterLiteralClass => {
const char_lit = @ptrCast(*const clang.CharacterLiteral, expr);
const val = char_lit.getValue();
// If the val is less than the max int then it fits.
return val <= width_max_int;
},
.IntegerLiteralClass => {
const int_lit = @ptrCast(*const clang.IntegerLiteral, expr);
var eval_result: clang.ExprEvalResult = undefined;
if (!int_lit.EvaluateAsInt(&eval_result, c.clang_context)) {
return false;
}
const int = eval_result.Val.getInt();
return int.lessThanEqual(width_max_int);
},
else => unreachable,
}
}
fn transInitListExprRecord(
c: *Context,
scope: *Scope,
@ -2331,7 +2375,7 @@ fn transDefault(
fn transConstantExpr(c: *Context, scope: *Scope, expr: *const clang.Expr, used: ResultUsed) TransError!Node {
var result: clang.ExprEvalResult = undefined;
if (!expr.EvaluateAsConstantExpr(&result, .EvaluateForCodeGen, c.clang_context))
if (!expr.evaluateAsConstantExpr(&result, .EvaluateForCodeGen, c.clang_context))
return fail(c, error.UnsupportedTranslation, expr.getBeginLoc(), "invalid constant expression", .{});
switch (result.Val.getKind()) {
@ -3171,7 +3215,7 @@ fn qualTypeIsBoolean(qt: clang.QualType) bool {
return qualTypeCanon(qt).isBooleanType();
}
fn qualTypeIntBitWidth(c: *Context, qt: clang.QualType, source_loc: clang.SourceLocation) !u32 {
fn qualTypeIntBitWidth(c: *Context, qt: clang.QualType) !u32 {
const ty = qt.getTypePtr();
switch (ty.getTypeClass()) {
@ -3211,12 +3255,10 @@ fn qualTypeIntBitWidth(c: *Context, qt: clang.QualType, source_loc: clang.Source
},
else => return 0,
}
unreachable;
}
fn qualTypeToLog2IntRef(c: *Context, qt: clang.QualType, source_loc: clang.SourceLocation) !Node {
const int_bit_width = try qualTypeIntBitWidth(c, qt, source_loc);
const int_bit_width = try qualTypeIntBitWidth(c, qt);
if (int_bit_width != 0) {
// we can perform the log2 now.

View File

@ -2244,6 +2244,11 @@ unsigned ZigClangAPSInt_getNumWords(const ZigClangAPSInt *self) {
return casted->getNumWords();
}
bool ZigClangAPSInt_lessThanEqual(const ZigClangAPSInt *self, uint64_t rhs) {
auto casted = reinterpret_cast<const llvm::APSInt *>(self);
return casted->ule(rhs);
}
uint64_t ZigClangAPInt_getLimitedValue(const ZigClangAPInt *self, uint64_t limit) {
auto casted = reinterpret_cast<const llvm::APInt *>(self);
return casted->getLimitedValue(limit);

View File

@ -1097,6 +1097,7 @@ ZIG_EXTERN_C const struct ZigClangAPSInt *ZigClangAPSInt_negate(const struct Zig
ZIG_EXTERN_C void ZigClangAPSInt_free(const struct ZigClangAPSInt *self);
ZIG_EXTERN_C const uint64_t *ZigClangAPSInt_getRawData(const struct ZigClangAPSInt *self);
ZIG_EXTERN_C unsigned ZigClangAPSInt_getNumWords(const struct ZigClangAPSInt *self);
ZIG_EXTERN_C bool ZigClangAPSInt_lessThanEqual(const struct ZigClangAPSInt *self, uint64_t rhs);
ZIG_EXTERN_C uint64_t ZigClangAPInt_getLimitedValue(const struct ZigClangAPInt *self, uint64_t limit);

View File

@ -313,22 +313,22 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
, &[_][]const u8{
\\pub const uuid_t = [16]u8;
\\pub const UUID_NULL: uuid_t = [16]u8{
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\ 0,
\\ 0,
\\ 0,
\\ 0,
\\ 0,
\\ 0,
\\ 0,
\\ 0,
\\ 0,
\\ 0,
\\ 0,
\\ 0,
\\ 0,
\\ 0,
\\ 0,
\\ 0,
\\};
});
@ -382,10 +382,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\};
\\pub export var ub: union_unnamed_1 = union_unnamed_1{
\\ .c = [4]u8{
\\ @bitCast(u8, @truncate(i8, @as(c_int, 'a'))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 'b'))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 'b'))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 'a'))),
\\ 'a',
\\ 'b',
\\ 'b',
\\ 'a',
\\ },
\\};
});
@ -512,7 +512,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
, &[_][]const u8{
\\pub export fn foo() void {
\\ var a: c_int = undefined;
\\ var b: u8 = @bitCast(u8, @truncate(i8, @as(c_int, 123)));
\\ var b: u8 = 123;
\\ const c: c_int = undefined;
\\ const d: c_uint = @bitCast(c_uint, @as(c_int, 440));
\\ var e: c_int = 10;
@ -1468,7 +1468,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
, &[_][]const u8{
\\pub fn foo() callconv(.C) void {
\\ var arr: [10]u8 = [1]u8{
\\ @bitCast(u8, @truncate(i8, @as(c_int, 1))),
\\ 1,
\\ } ++ [1]u8{0} ** 9;
\\ var arr1: [10][*c]u8 = [1][*c]u8{
\\ null,
@ -1721,13 +1721,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\ unsigned d = 440;
\\}
, &[_][]const u8{
\\pub var a: c_long = @bitCast(c_long, @as(c_long, @as(c_int, 2)));
\\pub var b: c_long = @bitCast(c_long, @as(c_long, @as(c_int, 2)));
\\pub var a: c_long = 2;
\\pub var b: c_long = 2;
\\pub var c: c_int = 4;
\\pub export fn foo(arg_c_1: u8) void {
\\ var c_1 = arg_c_1;
\\ var a_2: c_int = undefined;
\\ var b_3: u8 = @bitCast(u8, @truncate(i8, @as(c_int, 123)));
\\ var b_3: u8 = 123;
\\ b_3 = @bitCast(u8, @truncate(i8, a_2));
\\ {
\\ var d: c_int = 5;
@ -1838,7 +1838,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\ };
\\ }
\\ }
\\ var i: u8 = @bitCast(u8, @truncate(i8, @as(c_int, 2)));
\\ var i: u8 = 2;
\\}
});
@ -1846,7 +1846,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\unsigned anyerror = 2;
\\#define noreturn _Noreturn
, &[_][]const u8{
\\pub export var anyerror_1: c_uint = @bitCast(c_uint, @as(c_int, 2));
\\pub export var anyerror_1: c_uint = 2;
,
\\pub const noreturn_2 = @compileError("unable to translate C expr: unexpected token .Keyword_noreturn");
});
@ -1860,7 +1860,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\pub export var a: f32 = @floatCast(f32, 3.1415);
\\pub export var b: f64 = 3.1415;
\\pub export var c: c_int = @floatToInt(c_int, 3.1415);
\\pub export var d: f64 = @intToFloat(f64, @as(c_int, 3));
\\pub export var d: f64 = 3;
});
cases.add("conditional operator",
@ -2009,7 +2009,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\}
});
// TODO translate-c should in theory be able to figure out to drop all these casts
cases.add("escape sequences",
\\const char *escapes() {
\\char a = '\'',
@ -2028,17 +2027,17 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\
, &[_][]const u8{
\\pub export fn escapes() [*c]const u8 {
\\ var a: u8 = @bitCast(u8, @truncate(i8, @as(c_int, '\'')));
\\ var b: u8 = @bitCast(u8, @truncate(i8, @as(c_int, '\\')));
\\ var c: u8 = @bitCast(u8, @truncate(i8, @as(c_int, '\x07')));
\\ var d: u8 = @bitCast(u8, @truncate(i8, @as(c_int, '\x08')));
\\ var e: u8 = @bitCast(u8, @truncate(i8, @as(c_int, '\x0c')));
\\ var f: u8 = @bitCast(u8, @truncate(i8, @as(c_int, '\n')));
\\ var g: u8 = @bitCast(u8, @truncate(i8, @as(c_int, '\r')));
\\ var h: u8 = @bitCast(u8, @truncate(i8, @as(c_int, '\t')));
\\ var i: u8 = @bitCast(u8, @truncate(i8, @as(c_int, '\x0b')));
\\ var j: u8 = @bitCast(u8, @truncate(i8, @as(c_int, '\x00')));
\\ var k: u8 = @bitCast(u8, @truncate(i8, @as(c_int, '\"')));
\\ var a: u8 = '\'';
\\ var b: u8 = '\\';
\\ var c: u8 = '\x07';
\\ var d: u8 = '\x08';
\\ var e: u8 = '\x0c';
\\ var f: u8 = '\n';
\\ var g: u8 = '\r';
\\ var h: u8 = '\t';
\\ var i: u8 = '\x0b';
\\ var j: u8 = '\x00';
\\ var k: u8 = '\"';
\\ return "\'\\\x07\x08\x0c\n\r\t\x0b\x00\"";
\\}
});
@ -2308,8 +2307,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
, &[_][]const u8{
\\pub export fn foo() void {
\\ var a: [10]c_longlong = undefined;
\\ var i: c_longlong = @bitCast(c_longlong, @as(c_longlong, @as(c_int, 0)));
\\ a[@intCast(usize, i)] = @bitCast(c_longlong, @as(c_longlong, @as(c_int, 0)));
\\ var i: c_longlong = 0;
\\ a[@intCast(usize, i)] = 0;
\\}
});
@ -2321,8 +2320,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
, &[_][]const u8{
\\pub export fn foo() void {
\\ var a: [10]c_uint = undefined;
\\ var i: c_uint = @bitCast(c_uint, @as(c_int, 0));
\\ a[i] = @bitCast(c_uint, @as(c_int, 0));
\\ var i: c_uint = 0;
\\ a[i] = 0;
\\}
});
@ -2527,7 +2526,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
, &[_][]const u8{
\\pub export fn foo() void {
\\ var i: c_int = 0;
\\ var u: c_uint = @bitCast(c_uint, @as(c_int, 0));
\\ var u: c_uint = 0;
\\ i += 1;
\\ i -= 1;
\\ u +%= 1;
@ -2614,7 +2613,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
, &[_][]const u8{
\\pub export fn foo() void {
\\ var a: c_int = 0;
\\ var b: c_uint = @bitCast(c_uint, @as(c_int, 0));
\\ var b: c_uint = 0;
\\ a += blk: {
\\ const ref = &a;
\\ ref.* += @as(c_int, 1);
@ -2692,7 +2691,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\}
, &[_][]const u8{
\\pub export fn foo() void {
\\ var a: c_uint = @bitCast(c_uint, @as(c_int, 0));
\\ var a: c_uint = 0;
\\ a +%= blk: {
\\ const ref = &a;
\\ ref.* +%= @bitCast(c_uint, @as(c_int, 1));
@ -2752,7 +2751,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
, &[_][]const u8{
\\pub export fn foo() void {
\\ var i: c_int = 0;
\\ var u: c_uint = @bitCast(c_uint, @as(c_int, 0));
\\ var u: c_uint = 0;
\\ i += 1;
\\ i -= 1;
\\ u +%= 1;