diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index 4ecb22116..9051a171a 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -1300,7 +1300,7 @@ void llvm_emit_cast(GenContext *c, CastKind cast_kind, BEValue *value, Type *to_ llvm_value_rvalue(c, value); value->value = type_convert_will_trunc(to_type, from_type) ? LLVMBuildTrunc(c->builder, value->value, llvm_get_type(c, to_type), "siuitrunc") - : LLVMBuildZExt(c->builder, value->value, llvm_get_type(c, to_type), "siuiext"); + : LLVMBuildSExt(c->builder, value->value, llvm_get_type(c, to_type), "siuiext"); break; case CAST_SIFP: llvm_value_rvalue(c, value); diff --git a/src/compiler/sema_casts.c b/src/compiler/sema_casts.c index 6cfd83fe3..f7cb1a092 100644 --- a/src/compiler/sema_casts.c +++ b/src/compiler/sema_casts.c @@ -245,6 +245,13 @@ bool lit_integer_to_enum(Expr *expr, Type *canonical, Type *type) static bool int_conversion(Expr *expr, CastKind kind, Type *canonical, Type *type) { + // Fold pointer casts if narrowing + if (expr->expr_kind == EXPR_CAST && expr->cast_expr.kind == CAST_PTRXI + && type_size(type) <= type_size(expr->type)) + { + expr->type = type; + return true; + } if (insert_runtime_cast_unless_const(expr, kind, type)) return true; expr->const_expr.ixx = int_conv(expr->const_expr.ixx, canonical->type_kind); diff --git a/test/test_suite/cast/cast_from_ptr.c3t b/test/test_suite/cast/cast_from_ptr.c3t new file mode 100644 index 000000000..5fd784a32 --- /dev/null +++ b/test/test_suite/cast/cast_from_ptr.c3t @@ -0,0 +1,18 @@ +module test; + +fn void tester() +{ + int *x; + short y = (short)((uptr)(x)); + uptr z = (uptr)((short)((uptr)(x))); +} + +/* #expect: test.ll + + %0 = load i32*, i32** %x, align 8 + %ptrxi = ptrtoint i32* %0 to i16 + store i16 %ptrxi, i16* %y, align 2 + %1 = load i32*, i32** %x, align 8 + %ptrxi1 = ptrtoint i32* %1 to i16 + %siuiext = sext i16 %ptrxi1 to i64 + store i64 %siuiext, i64* %z, align 8 diff --git a/test/test_suite/clang/2002-01_02.c3t b/test/test_suite/clang/2002-01_02.c3t index 134cb61e5..fc6e621f7 100644 --- a/test/test_suite/clang/2002-01_02.c3t +++ b/test/test_suite/clang/2002-01_02.c3t @@ -234,9 +234,8 @@ if.then: ; preds = %loop.body %3 = load %Edge_rec*, %Edge_rec** %basel, align 8 %4 = getelementptr inbounds %Edge_rec, %Edge_rec* %3, i32 0, i32 1 %5 = load %Edge_rec*, %Edge_rec** %4, align 8 - %ptrxi = ptrtoint %Edge_rec* %5 to i64 - %sisitrunc = trunc i64 %ptrxi to i32 - ret i32 %sisitrunc + %ptrxi = ptrtoint %Edge_rec* %5 to i32 + ret i32 %ptrxi if.exit: ; preds = %loop.body br label %loop.body diff --git a/test/test_suite/functions/test_regression.c3t b/test/test_suite/functions/test_regression.c3t index 265e1b4a1..f728773d8 100644 --- a/test/test_suite/functions/test_regression.c3t +++ b/test/test_suite/functions/test_regression.c3t @@ -476,7 +476,7 @@ loop.cond: ; preds = %loop.body, %entry loop.body: ; preds = %loop.cond %6 = load i32, i32* %i, align 4 %7 = load i32, i32* %i, align 4 - %siuiext = zext i32 %7 to i64 + %siuiext = sext i32 %7 to i64 %8 = call i32 @"std::array::linkedlist.int.LinkedList__get"(%LinkedList* %list, i64 %siuiext) %9 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([17 x i8], [17 x i8]* @.str.2, i32 0, i32 0), i32 %6, i32 %8) %10 = load i32, i32* %i, align 4 @@ -511,7 +511,7 @@ loop.cond2: ; preds = %loop.body5, %loop.e loop.body5: ; preds = %loop.cond2 %16 = load i32, i32* %i1, align 4 %17 = load i32, i32* %i1, align 4 - %siuiext6 = zext i32 %17 to i64 + %siuiext6 = sext i32 %17 to i64 %18 = call i32 @"std::array::list.int.List__get"(%List* %array, i64 %siuiext6) %19 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([17 x i8], [17 x i8]* @.str.5, i32 0, i32 0), i32 %16, i32 %18) %20 = load i32, i32* %i1, align 4 diff --git a/test/test_suite/functions/test_regression_mingw.c3t b/test/test_suite/functions/test_regression_mingw.c3t index 7b7ae7959..36059aa20 100644 --- a/test/test_suite/functions/test_regression_mingw.c3t +++ b/test/test_suite/functions/test_regression_mingw.c3t @@ -538,7 +538,7 @@ loop.cond: ; preds = %loop.body, %entry loop.body: ; preds = %loop.cond %6 = load i32, i32* %i, align 4 %7 = load i32, i32* %i, align 4 - %siuiext = zext i32 %7 to i64 + %siuiext = sext i32 %7 to i64 %8 = call i32 @"std::array::linkedlist.int.LinkedList__get"(%LinkedList* %list, i64 %siuiext) %9 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([17 x i8], [17 x i8]* @.str.2, i32 0, i32 0), i32 %6, i32 %8) %10 = load i32, i32* %i, align 4 @@ -573,7 +573,7 @@ loop.cond2: ; preds = %loop.body5, %loop.e loop.body5: ; preds = %loop.cond2 %16 = load i32, i32* %i1, align 4 %17 = load i32, i32* %i1, align 4 - %siuiext6 = zext i32 %17 to i64 + %siuiext6 = sext i32 %17 to i64 %18 = call i32 @"std::array::list.int.List__get"(%List* %array, i64 %siuiext6) %19 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([17 x i8], [17 x i8]* @.str.5, i32 0, i32 0), i32 %16, i32 %18) %20 = load i32, i32* %i1, align 4