Skip to content

Commit 33f2668

Browse files
authored
[CIR] Upstream handling of integral-to-pointer casts (#161653)
Fix #153658 Handle integral to pointer casts and port the relevant `cast.cpp` test cases from incubator.
1 parent f8ba534 commit 33f2668

File tree

3 files changed

+68
-0
lines changed

3 files changed

+68
-0
lines changed

clang/include/clang/CIR/Dialect/IR/CIRDataLayout.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
#include "mlir/Dialect/DLTI/DLTI.h"
1616
#include "mlir/IR/BuiltinOps.h"
17+
#include "clang/CIR/Dialect/IR/CIRTypes.h"
1718

1819
namespace cir {
1920

@@ -81,6 +82,18 @@ class CIRDataLayout {
8182
}
8283

8384
llvm::TypeSize getTypeSizeInBits(mlir::Type ty) const;
85+
86+
llvm::TypeSize getPointerTypeSizeInBits(mlir::Type ty) const {
87+
assert(mlir::isa<cir::PointerType>(ty) &&
88+
"This should only be called with a pointer type");
89+
return layout.getTypeSizeInBits(ty);
90+
}
91+
92+
mlir::Type getIntPtrType(mlir::Type ty) const {
93+
assert(mlir::isa<cir::PointerType>(ty) && "Expected pointer type");
94+
return cir::IntType::get(ty.getContext(), getPointerTypeSizeInBits(ty),
95+
false);
96+
}
8497
};
8598

8699
} // namespace cir

clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1893,6 +1893,28 @@ mlir::Value ScalarExprEmitter::VisitCastExpr(CastExpr *ce) {
18931893
}
18941894
return v;
18951895
}
1896+
case CK_IntegralToPointer: {
1897+
mlir::Type destCIRTy = cgf.convertType(destTy);
1898+
mlir::Value src = Visit(const_cast<Expr *>(subExpr));
1899+
1900+
// Properly resize by casting to an int of the same size as the pointer.
1901+
// Clang's IntegralToPointer includes 'bool' as the source, but in CIR
1902+
// 'bool' is not an integral type. So check the source type to get the
1903+
// correct CIR conversion.
1904+
mlir::Type middleTy = cgf.cgm.getDataLayout().getIntPtrType(destCIRTy);
1905+
mlir::Value middleVal = builder.createCast(
1906+
subExpr->getType()->isBooleanType() ? cir::CastKind::bool_to_int
1907+
: cir::CastKind::integral,
1908+
src, middleTy);
1909+
1910+
if (cgf.cgm.getCodeGenOpts().StrictVTablePointers) {
1911+
cgf.cgm.errorNYI(subExpr->getSourceRange(),
1912+
"IntegralToPointer: strict vtable pointers");
1913+
return {};
1914+
}
1915+
1916+
return builder.createIntToPtr(middleVal, destCIRTy);
1917+
}
18961918

18971919
case CK_ArrayToPointerDecay:
18981920
return cgf.emitArrayToPointerDecay(subExpr).getPointer();

clang/test/CIR/CodeGen/cast.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,3 +131,36 @@ void bitcast() {
131131

132132
// LLVM: %[[D_VEC:.*]] = load <2 x double>, ptr {{.*}}, align 16
133133
// LLVM: %[[I_VEC:.*]] = bitcast <2 x double> %[[D_VEC]] to <4 x i32>
134+
135+
void f(long int start) {
136+
void *p = (void*)start;
137+
}
138+
// CIR: %[[L:.*]] = cir.load {{.*}} : !cir.ptr<!s64i>, !s64i
139+
// CIR: %[[MID:.*]] = cir.cast integral %[[L]] : !s64i -> !u64i
140+
// CIR: cir.cast int_to_ptr %[[MID]] : !u64i -> !cir.ptr<!void>
141+
142+
// LLVM-LABEL: define{{.*}} void @_Z1fl(i64 %0)
143+
// LLVM: %[[ADDR:.*]] = alloca i64, i64 1, align 8
144+
// LLVM: %[[PADDR:.*]] = alloca ptr, i64 1, align 8
145+
// LLVM: store i64 %0, ptr %[[ADDR]], align 8
146+
// LLVM: %[[L:.*]] = load i64, ptr %[[ADDR]], align 8
147+
// LLVM: %[[PTR:.*]] = inttoptr i64 %[[L]] to ptr
148+
// LLVM: store ptr %[[PTR]], ptr %[[PADDR]], align 8
149+
// LLVM: ret void
150+
151+
struct A { int x; };
152+
153+
void int_cast(long ptr) {
154+
((A *)ptr)->x = 0;
155+
}
156+
// CIR: cir.cast int_to_ptr {{.*}} : !u64i -> !cir.ptr<!rec_A>
157+
// LLVM: inttoptr {{.*}} to ptr
158+
159+
void null_cast(long) {
160+
*(int *)0 = 0;
161+
((A *)0)->x = 0;
162+
}
163+
// CIR: %[[NULLPTR:.*]] = cir.const #cir.ptr<null> : !cir.ptr<!s32i>
164+
// CIR: cir.store{{.*}} %{{.*}}, %[[NULLPTR]] : !s32i, !cir.ptr<!s32i>
165+
// CIR: %[[NULLPTR_A:.*]] = cir.const #cir.ptr<null> : !cir.ptr<!rec_A>
166+
// CIR: %[[A_X:.*]] = cir.get_member %[[NULLPTR_A]][0] {name = "x"} : !cir.ptr<!rec_A> -> !cir.ptr<!s32i>

0 commit comments

Comments
 (0)