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
36 changes: 23 additions & 13 deletions clang/include/clang/CIR/Dialect/IR/CIROps.td
Original file line number Diff line number Diff line change
Expand Up @@ -331,29 +331,39 @@ def CIR_DynamicCastOp : CIR_Op<"dyn_cast"> {
// ObjSizeOp
//===----------------------------------------------------------------------===//

def CIR_SizeInfoType : CIR_I32EnumAttr< "SizeInfoType", "size info type", [
I32EnumAttrCase<"Min", 0, "min">,
I32EnumAttrCase<"Max", 1, "max">
]>;

def CIR_ObjSizeOp : CIR_Op<"objsize", [Pure]> {
let summary = "Conversion between values of different types";
let summary = "Implements llvm.objsize builtin.";
let description = [{
The `cir.objsize` operation models the behavior of the `llvm.objectsize`
builtins in Clang. It returns the number of accessible bytes past ptr.

The `kind` argument determines whether `cir.objsize` returns 0 (if
true) or -1 (if false) when the object size is unknown. Corresponds to
`llvm.objectsize`'s `min` argument.

The `dynamic` attribute determines if the value should be evaluated at
runtime. Corresponds to `llvm.objectsize`'s `dynamic` argument.

Example:

```mlir
%size = cir.objsize min %ptr : !cir.ptr<i32> -> i64
%dsize = cir.objsize max dynamic %ptr : !cir.ptr<i32> -> i64
```
}];

let arguments = (ins
CIR_PointerType:$ptr,
CIR_SizeInfoType:$kind,
UnitAttr:$min,
UnitAttr:$dynamic
);

let results = (outs CIR_AnyFundamentalIntType:$result);

let assemblyFormat = [{
`(`
$ptr `:` type($ptr) `,`
$kind
(`,` `dynamic` $dynamic^)?
`)`
`->` type($result) attr-dict
(`min` $min^) : (`max`)?
(`dynamic` $dynamic^)?
$ptr `:` qualified(type($ptr)) `->` qualified(type($result)) attr-dict
}];
}

Expand Down
7 changes: 3 additions & 4 deletions clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3010,12 +3010,11 @@ mlir::Value CIRGenFunction::emitBuiltinObjectSize(const Expr *E, unsigned Type,

// LLVM intrinsics (which CIR lowers to at some point, only supports 0
// and 2, account for that right now.
cir::SizeInfoType sizeInfoTy =
((Type & 2) != 0) ? cir::SizeInfoType::Min : cir::SizeInfoType::Max;
bool sizeInfoTy = ((Type & 2) != 0);
// TODO(cir): Heads up for LLVM lowering, For GCC compatibility,
// __builtin_object_size treat NULL as unknown size.
return builder.create<cir::ObjSizeOp>(getLoc(E->getSourceRange()), ResType,
Ptr, sizeInfoTy, IsDynamic);
return cir::ObjSizeOp::create(builder, getLoc(E->getSourceRange()), ResType,
Ptr, sizeInfoTy, IsDynamic);
}

mlir::Value CIRGenFunction::evaluateOrEmitBuiltinObjectSize(
Expand Down
26 changes: 14 additions & 12 deletions clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3375,18 +3375,20 @@ mlir::LogicalResult CIRToLLVMObjSizeOpLowering::matchAndRewrite(
auto llvmResTy = getTypeConverter()->convertType(op.getType());
auto loc = op->getLoc();

cir::SizeInfoType kindInfo = op.getKind();
auto falseValue =
rewriter.create<mlir::LLVM::ConstantOp>(loc, rewriter.getI1Type(), false);
auto trueValue =
rewriter.create<mlir::LLVM::ConstantOp>(loc, rewriter.getI1Type(), true);

replaceOpWithCallLLVMIntrinsicOp(
rewriter, op, "llvm.objectsize", llvmResTy,
mlir::ValueRange{adaptor.getPtr(),
kindInfo == cir::SizeInfoType::Max ? falseValue
: trueValue,
trueValue, op.getDynamic() ? trueValue : falseValue});
auto i1Ty = rewriter.getI1Type();

auto i1Val = [&rewriter, &loc, &i1Ty](bool val) {
return mlir::LLVM::ConstantOp::create(rewriter, loc, i1Ty, val);
};

// clang-format off
replaceOpWithCallLLVMIntrinsicOp(rewriter, op, "llvm.objectsize", llvmResTy, {
/*ptr=*/adaptor.getPtr(),
/*min=*/i1Val(op.getMin()),
/*nullunknown=*/i1Val(true),
/*dynamic=*/i1Val(op.getDynamic())
});
// clang-format on

return mlir::LogicalResult::success();
}
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CIR/CodeGen/libcall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ void t(const char* fmt, ...) {
// CHECK: %0 = cir.alloca !cir.ptr<!s8i>, !cir.ptr<!cir.ptr<!s8i>>, ["m", init] {alignment = 8 : i64}

// CHECK: %3 = cir.load{{.*}} %0 : !cir.ptr<!cir.ptr<!s8i>>, !cir.ptr<!s8i>
// CHECK: %4 = cir.objsize(%3 : <!s8i>, max) -> !u64i
// CHECK: %4 = cir.objsize max %3 : !cir.ptr<!s8i> -> !u64i
// CHECK: %5 = cir.call @_ZL6strlenPKcU17pass_object_size0(%3, %4) : (!cir.ptr<!s8i>, !u64i) -> !u64i

// CHECK: cir.func private @__vsnprintf_chk
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CIR/CodeGen/pass-object-size.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ void c() {
// CIR: cir.func no_proto dso_local @c()
// CIR: [[TMP0:%.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, %{{[0-9]+}} : !u64i, ["vla"] {alignment = 16 : i64}
// CIR: [[TMP1:%.*]] = cir.cast bitcast [[TMP0]] : !cir.ptr<!s32i> -> !cir.ptr<!void>
// CIR-NEXT: [[TMP2:%.*]] = cir.objsize([[TMP1]] : <!void>, max) -> !u64i
// CIR-NEXT: [[TMP2:%.*]] = cir.objsize max [[TMP1]] : !cir.ptr<!void> -> !u64i
// CIR-NEXT: cir.call @b([[TMP1]], [[TMP2]]) : (!cir.ptr<!void>, !u64i) -> ()
// CIR: [[TMP3:%.*]] = cir.cast bitcast [[TMP0]] : !cir.ptr<!s32i> -> !cir.ptr<!void>
// CIR: [[TMP4:%.*]] = cir.objsize([[TMP3]] : <!void>, min) -> !u64i
// CIR: [[TMP4:%.*]] = cir.objsize min [[TMP3]] : !cir.ptr<!void> -> !u64i
// CIR-NEXT: cir.call @e([[TMP3]], [[TMP4]]) : (!cir.ptr<!void>, !u64i) -> ()

// LLVM: define dso_local void @c()
Expand Down
8 changes: 4 additions & 4 deletions clang/test/CIR/IR/cir-ops.cir
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ module {
cir.func @os() {
%0 = cir.alloca !cir.ptr<!s8i>, !cir.ptr<!cir.ptr<!s8i>>, ["m", init] {alignment = 8 : i64}
%3 = cir.load %0 : !cir.ptr<!cir.ptr<!s8i>>, !cir.ptr<!s8i>
%4 = cir.objsize(%3 : <!s8i>, max) -> !u64i
%5 = cir.objsize(%3 : <!s8i>, min) -> !u64i
%4 = cir.objsize max %3 : !cir.ptr<!s8i> -> !u64i
%5 = cir.objsize min %3 : !cir.ptr<!s8i> -> !u64i
cir.return
}

Expand Down Expand Up @@ -105,8 +105,8 @@ module {
// CHECK: cir.func @os() {
// CHECK-NEXT: %0 = cir.alloca !cir.ptr<!s8i>, !cir.ptr<!cir.ptr<!s8i>>, ["m", init] {alignment = 8 : i64}
// CHECK-NEXT: %1 = cir.load %0 : !cir.ptr<!cir.ptr<!s8i>>, !cir.ptr<!s8i>
// CHECK-NEXT: %2 = cir.objsize(%1 : <!s8i>, max) -> !u64i
// CHECK-NEXT: %3 = cir.objsize(%1 : <!s8i>, min) -> !u64i
// CHECK-NEXT: %2 = cir.objsize max %1 : !cir.ptr<!s8i> -> !u64i
// CHECK-NEXT: %3 = cir.objsize min %1 : !cir.ptr<!s8i> -> !u64i
// CHECK-NEXT: cir.return
// CHECK-NEXT: }

Expand Down
Loading