Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion clang/include/clang/CIR/Dialect/IR/CIROps.td
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,15 @@ def CK_BitCast : I32EnumAttrCase<"bitcast", 4>;
def CK_FloatingCast : I32EnumAttrCase<"floating", 5>;
def CK_PtrToBoolean : I32EnumAttrCase<"ptr_to_bool", 6>;
def CK_FloatToIntegral : I32EnumAttrCase<"float_to_int", 7>;
def CK_IntegralToPointer : I32EnumAttrCase<"int_to_ptr", 8>;
def CK_PointerToIntegral : I32EnumAttrCase<"ptr_to_int", 9>;

def CastKind : I32EnumAttr<
"CastKind",
"cast kind",
[CK_IntegralToBoolean, CK_ArrayToPointerDecay, CK_IntegralCast,
CK_BitCast, CK_FloatingCast, CK_PtrToBoolean, CK_FloatToIntegral]> {
CK_BitCast, CK_FloatingCast, CK_PtrToBoolean, CK_FloatToIntegral,
CK_IntegralToPointer, CK_PointerToIntegral]> {
let cppNamespace = "::mlir::cir";
}

Expand Down
14 changes: 14 additions & 0 deletions clang/lib/CIR/CodeGen/CIRDataLayout.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

#include "mlir/Dialect/DLTI/DLTI.h"
#include "mlir/IR/BuiltinOps.h"
#include "clang/CIR/Dialect/IR/CIRTypes.h"

namespace cir {

Expand Down Expand Up @@ -60,6 +61,19 @@ class CIRDataLayout {
// Round up to the next alignment boundary.
return llvm::alignTo(getTypeStoreSize(Ty), layout.getTypeABIAlignment(Ty));
}

unsigned getPointerTypeSizeInBits(mlir::Type Ty) const {
assert(Ty.isa<mlir::cir::PointerType>() &&
"This should only be called with a pointer type");
return layout.getTypeSizeInBits(Ty);
}

mlir::Type getIntPtrType(mlir::Type Ty) const {
assert(Ty.isa<mlir::cir::PointerType>() && "Expected pointer type");
auto IntTy = mlir::cir::IntType::get(Ty.getContext(),
getPointerTypeSizeInBits(Ty), false);
return IntTy;
}
};

} // namespace cir
Expand Down
27 changes: 27 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

#include "clang/CIR/Dialect/IR/CIRAttrs.h"
#include "clang/CIR/Dialect/IR/CIRDialect.h"
#include "clang/CIR/Dialect/IR/CIROpsEnums.h"
#include "clang/CIR/Dialect/IR/CIRTypes.h"
#include "clang/CIR/Dialect/IR/FPEnv.h"

Expand Down Expand Up @@ -346,6 +347,32 @@ class CIRGenBuilderTy : public mlir::OpBuilder {
mlir::cir::UnaryOpKind::Not, value);
}

//===--------------------------------------------------------------------===//
// Cast/Conversion Operators
//===--------------------------------------------------------------------===//

mlir::Value createCast(mlir::cir::CastKind kind, mlir::Value src,
mlir::Type newTy) {
if (newTy == src.getType())
return src;
return create<mlir::cir::CastOp>(src.getLoc(), newTy, kind, src);
}

mlir::Value createIntCast(mlir::Value src, mlir::Type newTy) {
return create<mlir::cir::CastOp>(src.getLoc(), newTy,
mlir::cir::CastKind::integral, src);
}

mlir::Value createIntToPtr(mlir::Value src, mlir::Type newTy) {
return create<mlir::cir::CastOp>(src.getLoc(), newTy,
mlir::cir::CastKind::int_to_ptr, src);
}

mlir::Value createPtrToInt(mlir::Value src, mlir::Type newTy) {
return create<mlir::cir::CastOp>(src.getLoc(), newTy,
mlir::cir::CastKind::ptr_to_int, src);
}

mlir::Value createZExtOrBitCast(mlir::Location loc, mlir::Value src,
mlir::Type newTy) {
if (src.getType() == newTy)
Expand Down
23 changes: 19 additions & 4 deletions clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1102,10 +1102,25 @@ mlir::Value ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
assert(E->isGLValue() && "lvalue-to-rvalue applied to r-value!");
return Visit(const_cast<Expr *>(E));

case CK_IntegralToPointer:
llvm_unreachable("NYI");
case CK_PointerToIntegral:
llvm_unreachable("NYI");
case CK_IntegralToPointer: {
auto DestCIRTy = ConvertType(DestTy);
mlir::Value Src = Visit(const_cast<Expr *>(E));

// Properly resize by casting to an int of the same size as the pointer.
auto MiddleTy = CGF.CGM.getDataLayout().getIntPtrType(DestCIRTy);
auto MiddleVal = Builder.createIntCast(Src, MiddleTy);

if (CGF.CGM.getCodeGenOpts().StrictVTablePointers)
llvm_unreachable("NYI");

return Builder.createIntToPtr(MiddleVal, DestCIRTy);
}
case CK_PointerToIntegral: {
assert(!DestTy->isBooleanType() && "bool should use PointerToBool");
if (CGF.CGM.getCodeGenOpts().StrictVTablePointers)
llvm_unreachable("NYI");
return Builder.createPtrToInt(Visit(E), ConvertType(DestTy));
}
case CK_ToVoid: {
CGF.buildIgnoredExpr(E);
return nullptr;
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#ifndef LLVM_CLANG_LIB_CODEGEN_CIRGENMODULE_H
#define LLVM_CLANG_LIB_CODEGEN_CIRGENMODULE_H

#include "CIRDataLayout.h"
#include "CIRGenBuilder.h"
#include "CIRGenTypeCache.h"
#include "CIRGenTypes.h"
Expand Down Expand Up @@ -125,6 +126,11 @@ class CIRGenModule : public CIRGenTypeCache {
CIRGenTypes &getTypes() { return genTypes; }
const clang::LangOptions &getLangOpts() const { return langOpts; }
CIRGenFunction *getCurrCIRGenFun() const { return CurCGF; }
const CIRDataLayout getDataLayout() const {
// FIXME(cir): instead of creating a CIRDataLayout every time, set it as an
// attribute for the CIRModule class.
return {theModule};
}

CIRGenCXXABI &getCXXABI() const { return *ABI; }

Expand Down
3 changes: 3 additions & 0 deletions clang/lib/CIR/CodeGen/UnimplementedFeatureGuarding.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ struct UnimplementedFeature {
static bool addressSpaceInGlobalVar() { return false; }
static bool getASTAllocaAddressSpace() { return false; }

// Clang codegen options
static bool strictVTablePointers() { return false; }

// Unhandled global/linkage information.
static bool unnamedAddr() { return false; }
static bool setComdat() { return false; }
Expand Down
14 changes: 14 additions & 0 deletions clang/lib/CIR/Dialect/IR/CIRDialect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,20 @@ LogicalResult CastOp::verify() {
return emitOpError() << "requires !IntegerType for result";
return success();
}
case cir::CastKind::int_to_ptr: {
if (!srcType.dyn_cast<mlir::cir::IntType>())
return emitOpError() << "requires integer for source";
if (!resType.dyn_cast<mlir::cir::PointerType>())
return emitOpError() << "requires pointer for result";
return success();
}
case cir::CastKind::ptr_to_int: {
if (!srcType.dyn_cast<mlir::cir::PointerType>())
return emitOpError() << "requires pointer for source";
if (!resType.dyn_cast<mlir::cir::IntType>())
return emitOpError() << "requires integer for result";
return success();
}
}

llvm_unreachable("Unknown CastOp kind?");
Expand Down
24 changes: 24 additions & 0 deletions clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,22 @@ class CIRCastOpLowering : public mlir::OpConversionPattern<mlir::cir::CastOp> {

return castOp.emitError() << "NYI cast from " << srcTy << " to " << dstTy;
}
case mlir::cir::CastKind::int_to_ptr: {
auto dstTy = castOp.getType().cast<mlir::cir::PointerType>();
auto llvmSrcVal = adaptor.getOperands().front();
auto llvmDstTy = getTypeConverter()->convertType(dstTy);
rewriter.replaceOpWithNewOp<mlir::LLVM::IntToPtrOp>(castOp, llvmDstTy,
llvmSrcVal);
return mlir::success();
}
case mlir::cir::CastKind::ptr_to_int: {
auto dstTy = castOp.getType().cast<mlir::cir::IntType>();
auto llvmSrcVal = adaptor.getOperands().front();
auto llvmDstTy = getTypeConverter()->convertType(dstTy);
rewriter.replaceOpWithNewOp<mlir::LLVM::PtrToIntOp>(castOp, llvmDstTy,
llvmSrcVal);
return mlir::success();
}
default:
llvm_unreachable("NYI");
}
Expand Down Expand Up @@ -489,6 +505,14 @@ class CIRConstantLowering
op.getValue().cast<mlir::cir::IntAttr>().getValue());
} else if (op.getType().isa<mlir::FloatType>()) {
attr = op.getValue();
} else if (op.getType().isa<mlir::cir::PointerType>()) {
// Optimize with dedicated LLVM op for null pointers.
if (op.getValue().isa<mlir::cir::NullAttr>()) {
rewriter.replaceOpWithNewOp<mlir::LLVM::NullOp>(
op, typeConverter->convertType(op.getType()));
return mlir::success();
}
attr = op.getValue();
} else
return op.emitError("unsupported constant type");

Expand Down
7 changes: 6 additions & 1 deletion clang/test/CIR/CodeGen/cast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ unsigned char cxxstaticcast_0(unsigned int x) {
// CHECK: }


int cStyleCasts_0(unsigned x1, int x2, float x3) {
int cStyleCasts_0(unsigned x1, int x2, float x3, short x4) {
// CHECK: cir.func @_{{.*}}cStyleCasts_0{{.*}}

char a = (char)x1; // truncate
Expand All @@ -42,6 +42,11 @@ int cStyleCasts_0(unsigned x1, int x2, float x3) {
double g = (double)x3; // FP extension
// %{{[0-9]+}} = cir.cast(floating, %{{[0-9]+}} : f32), f64

long l = (long)(void*)x4; // Must sign extend before casting to pointer
// CHECK: %[[TMP:[0-9]+]] = cir.cast(integral, %{{[0-9]+}} : !s16i), !u64i
// CHECK: %[[TMP2:[0-9]+]] = cir.cast(int_to_ptr, %[[TMP]] : !u64i), !cir.ptr<!u8i>
// CHECK: %{{[0-9]+}} = cir.cast(ptr_to_int, %[[TMP2]] : !cir.ptr<!u8i>), !s64i

return 0;
}

Expand Down
9 changes: 9 additions & 0 deletions clang/test/CIR/Lowering/cast.cir
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
!s8i = !cir.int<s, 8>
!u32i = !cir.int<u, 32>
!u8i = !cir.int<u, 8>
!u64i = !cir.int<u, 64>

module {
cir.func @foo(%arg0: !s32i) -> !s32i {
Expand All @@ -31,6 +32,7 @@ module {
// MLIR: llvm.func @cStyleCasts(%arg0: i32, %arg1: i32) -> i32 {
%0 = cir.alloca !u32i, cir.ptr <!u32i>, ["x1", init] {alignment = 4 : i64}
%1 = cir.alloca !s32i, cir.ptr <!s32i>, ["x2", init] {alignment = 4 : i64}
%20 = cir.alloca !s16i, cir.ptr <!s16i>, ["x4", init] {alignment = 2 : i64}
%2 = cir.alloca !s32i, cir.ptr <!s32i>, ["__retval"] {alignment = 4 : i64}
%3 = cir.alloca !s8i, cir.ptr <!s8i>, ["a", init] {alignment = 1 : i64}
%4 = cir.alloca !s16i, cir.ptr <!s16i>, ["b", init] {alignment = 2 : i64}
Expand Down Expand Up @@ -59,6 +61,13 @@ module {
%17 = cir.cast(array_to_ptrdecay, %7 : !cir.ptr<!cir.array<!s32i x 3>>), !cir.ptr<!s32i>
// MLIR: %{{[0-9]+}} = llvm.getelementptr %{{[0-9]+}}[0] : (!llvm.ptr<array<3 x i32>>) -> !llvm.ptr<i32>
cir.store %17, %8 : !cir.ptr<!s32i>, cir.ptr <!cir.ptr<!s32i>>
%21 = cir.load %20 : cir.ptr <!s16i>, !s16i
%22 = cir.cast(integral, %21 : !s16i), !u64i
// MLIR: %[[TMP:[0-9]+]] = llvm.sext %{{[0-9]+}} : i16 to i64
%23 = cir.cast(int_to_ptr, %22 : !u64i), !cir.ptr<!u8i>
// MLIR: %[[TMP2:[0-9]+]] = llvm.inttoptr %[[TMP]] : i64 to !llvm.ptr<i8>
%24 = cir.cast(ptr_to_int, %23 : !cir.ptr<!u8i>), !s32i
// MLIR: %{{[0-9]+}} = llvm.ptrtoint %[[TMP2]] : !llvm.ptr<i8> to i32
%18 = cir.const(#cir.int<0> : !s32i) : !s32i
cir.store %18, %2 : !s32i, cir.ptr <!s32i>
%19 = cir.load %2 : cir.ptr <!s32i>, !s32i
Expand Down