https://github.com/adams381 updated https://github.com/llvm/llvm-project/pull/191482
>From 908e5f183e6eaa63670141cf80818f69857f53d9 Mon Sep 17 00:00:00 2001 From: Adam Smith <[email protected]> Date: Fri, 10 Apr 2026 11:10:38 -0700 Subject: [PATCH 1/3] [CIR] Add pass_object_size hidden parameter support Implement hidden parameter insertion for __attribute__((pass_object_size(N))). The compiler now emits an extra i64 parameter per annotated param, filled with __builtin_object_size at the call site (constant-folded when possible, otherwise via cir.objsize / @llvm.objectsize). Key changes: - appendParameterTypes adds canonical size_t for each param with hasPassObjectSize() - RequiredArgs::getFromProtoWithExtraSlots counts pass_object_size slots for variadic required-arg accounting - maybeEmitImplicitObjectSize calls evaluateOrEmitBuiltinObjectSize to fill the hidden param at call sites - buildFunctionArgList creates ImplicitParamDecl entries so callee bodies can load the passed size via sizeArguments - emitBuiltinObjectSize checks sizeArguments before falling back to cir.objsize, matching classic codegen behavior Made-with: Cursor --- clang/include/clang/CIR/MissingFeatures.h | 2 +- clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 24 +++++++- clang/lib/CIR/CodeGen/CIRGenCall.cpp | 34 ++++++++--- clang/lib/CIR/CodeGen/CIRGenFunction.cpp | 11 +++- clang/lib/CIR/CodeGen/CIRGenFunction.h | 5 ++ clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h | 6 +- clang/test/CIR/CodeGen/pass-object-size.c | 65 ++++++++++++++++++++++ 7 files changed, 133 insertions(+), 14 deletions(-) create mode 100644 clang/test/CIR/CodeGen/pass-object-size.c diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h index ac02433fb504a..ca857701b6b4f 100644 --- a/clang/include/clang/CIR/MissingFeatures.h +++ b/clang/include/clang/CIR/MissingFeatures.h @@ -109,7 +109,7 @@ struct MissingFeatures { static bool opCallSurroundingTry() { return false; } static bool opCallASTAttr() { return false; } static bool opCallObjCMethod() { return false; } - static bool opCallExtParameterInfo() { return false; } + static bool opCallCIRGenFuncInfoParamInfo() { return false; } static bool opCallCIRGenFuncInfoExtParamInfo() { return false; } static bool opCallChain() { return false; } diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp index 1a6aeef73fb79..62729839b6ae4 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp @@ -2581,11 +2581,33 @@ mlir::Value CIRGenFunction::emitVAArg(VAArgExpr *ve) { return cir::VAArgOp::create(builder, loc, type, vaList); } +/// Checks if using the result of __builtin_object_size(p, @p from) in place of +/// __builtin_object_size(p, @p to) is correct. +static bool areBOSTypesCompatible(int from, int to) { + return from == to || (from == 0 && to == 1) || (from == 3 && to == 2); +} + mlir::Value CIRGenFunction::emitBuiltinObjectSize(const Expr *e, unsigned type, cir::IntType resType, mlir::Value emittedE, bool isDynamic) { - assert(!cir::MissingFeatures::opCallImplicitObjectSizeArgs()); + // If this is a pass_object_size parameter, load the implicit size arg. + if (auto *d = dyn_cast<DeclRefExpr>(e->IgnoreParenImpCasts())) { + auto *param = dyn_cast<ParmVarDecl>(d->getDecl()); + auto *ps = d->getDecl()->getAttr<PassObjectSizeAttr>(); + if (param && ps && areBOSTypesCompatible(ps->getType(), type)) { + auto iter = sizeArguments.find(param); + assert(iter != sizeArguments.end()); + + const ImplicitParamDecl *sizeDecl = iter->second; + auto dIter = localDeclMap.find(sizeDecl); + assert(dIter != localDeclMap.end()); + + return emitLoadOfScalar(dIter->second, /*volatile=*/false, + getContext().getSizeType(), e->getBeginLoc(), + LValueBaseInfo(AlignmentSource::Decl)); + } + } // LLVM can't handle type=3 appropriately, and __builtin_object_size shouldn't // evaluate e for side-effects. In either case, just like original LLVM diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp b/clang/lib/CIR/CodeGen/CIRGenCall.cpp index 10b4528ff2aac..dc074491b4582 100644 --- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp @@ -710,20 +710,26 @@ static CanQual<FunctionProtoType> getFormalType(const CXXMethodDecl *md) { .getAs<FunctionProtoType>(); } -/// Adds the formal parameters in FPT to the given prefix. If any parameter in -/// FPT has pass_object_size_attrs, then we'll add parameters for those, too. +/// Adds the formal parameters in FPT to the given prefix. If any parameter in +/// FPT has pass_object_size attrs, then we'll add parameters for those, too. /// TODO(cir): this should be shared with LLVM codegen static void appendParameterTypes(const CIRGenTypes &cgt, SmallVectorImpl<CanQualType> &prefix, CanQual<FunctionProtoType> fpt) { - assert(!cir::MissingFeatures::opCallExtParameterInfo()); // Fast path: don't touch param info if we don't need to. if (!fpt->hasExtParameterInfos()) { prefix.append(fpt->param_type_begin(), fpt->param_type_end()); return; } - cgt.getCGModule().errorNYI("appendParameterTypes: hasExtParameterInfos"); + prefix.reserve(prefix.size() + fpt->getNumParams()); + auto extInfos = fpt->getExtParameterInfos(); + for (unsigned i = 0, e = fpt->getNumParams(); i != e; ++i) { + prefix.push_back(fpt->getParamType(i)); + if (extInfos[i].hasPassObjectSize()) + prefix.push_back(cgt.getASTContext().getCanonicalType( + cgt.getASTContext().getSizeType())); + } } const CIRGenFunctionInfo & @@ -858,10 +864,14 @@ arrangeFreeFunctionLikeCall(CIRGenTypes &cgt, CIRGenModule &cgm, RequiredArgs required = RequiredArgs::All; if (const auto *proto = dyn_cast<FunctionProtoType>(fnType)) { - if (proto->isVariadic()) - required = RequiredArgs::getFromProtoWithExtraSlots(proto, 0); + unsigned numExtraSlots = 0; if (proto->hasExtParameterInfos()) - cgm.errorNYI("call to functions with extra parameter info"); + for (const auto &info : proto->getExtParameterInfos()) + if (info.hasPassObjectSize()) + ++numExtraSlots; + if (proto->isVariadic()) + required = + RequiredArgs::getFromProtoWithExtraSlots(proto, numExtraSlots); } else if (cgm.getTargetCIRGenInfo().isNoProtoCallVariadic( cast<FunctionNoProtoType>(fnType))) cgm.errorNYI("call to function without a prototype"); @@ -1397,8 +1407,14 @@ void CIRGenFunction::emitCallArgs( if (!ps) return; - assert(!cir::MissingFeatures::opCallImplicitObjectSizeArgs()); - cgm.errorNYI("emit implicit object size for call arg"); + QualType sizeTy = getContext().getSizeType(); + auto t = cast<cir::IntType>(cgm.sizeTy); + assert(emittedArg.getValue() && "We emitted nothing for the arg?"); + mlir::Value v = evaluateOrEmitBuiltinObjectSize( + arg, ps->getType(), t, emittedArg.getValue(), ps->isDynamic()); + args.add(RValue::get(v), sizeTy); + if (!leftToRight) + std::swap(args.back(), *(&args.back() - 1)); }; // Evaluate each argument in the appropriate order. diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp index fcfbeb809371e..263641fe0023f 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp @@ -999,8 +999,15 @@ clang::QualType CIRGenFunction::buildFunctionArgList(clang::GlobalDecl gd, if (passedParams) { for (auto *param : fd->parameters()) { args.push_back(param); - if (param->hasAttr<PassObjectSizeAttr>()) - cgm.errorNYI(param->getSourceRange(), "pass-object-size attribute"); + if (!param->hasAttr<PassObjectSizeAttr>()) + continue; + + auto *implicit = ImplicitParamDecl::Create( + getContext(), param->getDeclContext(), param->getLocation(), + /*Id=*/nullptr, getContext().getSizeType(), + ImplicitParamKind::Other); + sizeArguments[param] = implicit; + args.push_back(implicit); } } diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h index 4f0f33a933e01..5cfde7ac18066 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.h +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h @@ -174,6 +174,11 @@ class CIRGenFunction : public CIRGenTypeCache { ImplicitParamDecl *cxxStructorImplicitParamDecl{}; mlir::Value cxxStructorImplicitParamValue{}; + /// If a ParmVarDecl had the pass_object_size attribute, this will contain a + /// mapping from said ParmVarDecl to its implicit "object_size" parameter. + llvm::SmallDenseMap<const ParmVarDecl *, const ImplicitParamDecl *, 2> + sizeArguments; + /// The value of 'this' to sue when evaluating CXXDefaultInitExprs within this /// expression. Address cxxDefaultInitExprThis = Address::invalid(); diff --git a/clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h b/clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h index 00b107296d9fc..67a33d1e75401 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h +++ b/clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h @@ -51,7 +51,11 @@ class RequiredArgs { return All; if (prototype->hasExtParameterInfos()) - llvm_unreachable("NYI"); + additional += llvm::count_if( + prototype->getExtParameterInfos(), + [](const clang::FunctionProtoType::ExtParameterInfo &extInfo) { + return extInfo.hasPassObjectSize(); + }); return RequiredArgs(prototype->getNumParams() + additional); } diff --git a/clang/test/CIR/CodeGen/pass-object-size.c b/clang/test/CIR/CodeGen/pass-object-size.c new file mode 100644 index 0000000000000..55337baa7e0c8 --- /dev/null +++ b/clang/test/CIR/CodeGen/pass-object-size.c @@ -0,0 +1,65 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll +// RUN: FileCheck --check-prefix=LLVM --input-file=%t-cir.ll %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll +// RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s + +void b(void *__attribute__((pass_object_size(0)))); +void e(void *__attribute__((pass_object_size(2)))); + +// CIR: cir.func private @b(!cir.ptr<!void> {llvm.noundef}, !u64i {llvm.noundef}) + +void test_constant() { + int a; + b(&a); +} + +// CIR: cir.func {{.*}} @test_constant() +// CIR: %[[ALLOCA:.*]] = cir.alloca !s32i, !cir.ptr<!s32i> +// CIR: %[[CAST:.*]] = cir.cast bitcast %[[ALLOCA]] : !cir.ptr<!s32i> -> !cir.ptr<!void> +// CIR: %[[SIZE:.*]] = cir.const #cir.int<4> : !u64i +// CIR: cir.call @b(%[[CAST]], %[[SIZE]]) : (!cir.ptr<!void> {{.*}}, !u64i {{.*}}) -> () + +// CIR: cir.func private @e(!cir.ptr<!void> {llvm.noundef}, !u64i {llvm.noundef}) + +// LLVM: declare void @b(ptr noundef, i64 noundef) + +// LLVM: define dso_local void @test_constant() +// LLVM: %[[ALLOCA:.*]] = alloca i32 +// LLVM: call void @b(ptr noundef %[[ALLOCA]], i64 noundef 4) + +void test_vla(int n) { + int d[n]; + b(d); + e(d); +} + +// CIR: cir.func {{.*}} @test_vla +// CIR: %[[VLA:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, %{{.*}} : !u64i, ["d"] {alignment = 16 : i64} +// CIR: %[[CAST1:.*]] = cir.cast bitcast %[[VLA]] : !cir.ptr<!s32i> -> !cir.ptr<!void> +// CIR: %[[SIZE1:.*]] = cir.objsize max nullunknown %[[CAST1]] : !cir.ptr<!void> -> !u64i +// CIR: cir.call @b(%[[CAST1]], %[[SIZE1]]) : (!cir.ptr<!void> {{.*}}, !u64i {{.*}}) -> () +// CIR: %[[CAST2:.*]] = cir.cast bitcast %[[VLA]] : !cir.ptr<!s32i> -> !cir.ptr<!void> +// CIR: %[[SIZE2:.*]] = cir.objsize min nullunknown %[[CAST2]] : !cir.ptr<!void> -> !u64i +// CIR: cir.call @e(%[[CAST2]], %[[SIZE2]]) : (!cir.ptr<!void> {{.*}}, !u64i {{.*}}) -> () + +// LLVM: define dso_local void @test_vla(i32 noundef %{{.*}}) +// LLVM: %[[VLA:.*]] = alloca i32, i64 %{{.*}}, align 16 +// LLVM: %[[SIZE1:.*]] = call i64 @llvm.objectsize.i64.p0(ptr %[[VLA]], i1 false, i1 true, i1 false) +// LLVM: call void @b(ptr noundef %[[VLA]], i64 noundef %[[SIZE1]]) +// LLVM: %[[SIZE2:.*]] = call i64 @llvm.objectsize.i64.p0(ptr %[[VLA]], i1 true, i1 true, i1 false) +// LLVM: call void @e(ptr noundef %[[VLA]], i64 noundef %[[SIZE2]]) + +// OGCG: define dso_local void @test_constant() +// OGCG: %[[A:.*]] = alloca i32 +// OGCG: call void @b(ptr noundef %[[A]], i64 noundef 4) + +// OGCG: declare void @b(ptr noundef, i64 noundef) + +// OGCG: define dso_local void @test_vla(i32 noundef %{{.*}}) +// OGCG: %[[VLA:.*]] = alloca i32, i64 %{{.*}}, align 16 +// OGCG: %[[SIZE1:.*]] = call i64 @llvm.objectsize.i64.p0(ptr %[[VLA]], i1 false, i1 true, i1 false) +// OGCG: call void @b(ptr noundef %[[VLA]], i64 noundef %[[SIZE1]]) +// OGCG: %[[SIZE2:.*]] = call i64 @llvm.objectsize.i64.p0(ptr %[[VLA]], i1 true, i1 true, i1 false) +// OGCG: call void @e(ptr noundef %[[VLA]], i64 noundef %[[SIZE2]]) >From 2049ec9c172ac0e71843c6a99f6179b15f39992d Mon Sep 17 00:00:00 2001 From: Adam Smith <[email protected]> Date: Mon, 13 Apr 2026 15:41:20 -0700 Subject: [PATCH 2/3] [CIR] Address review feedback on pass_object_size - Add classic codegen comment explaining areBOSTypesCompatible - Remove opCallImplicitObjectSizeArgs from MissingFeatures.h - Use getCanonicalSizeType() in appendParameterTypes - Add reserve comment from classic codegen - Handle extParameterInfo at call sites: count pass_object_size slots in RequiredArgs instead of errorNYI - Use explicit types instead of auto Addresses review feedback from @andykaylor. Made-with: Cursor --- clang/include/clang/CIR/MissingFeatures.h | 1 - clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 4 ++++ clang/lib/CIR/CodeGen/CIRGenCall.cpp | 13 +++++++------ 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h index ca857701b6b4f..6224924ceb1d5 100644 --- a/clang/include/clang/CIR/MissingFeatures.h +++ b/clang/include/clang/CIR/MissingFeatures.h @@ -98,7 +98,6 @@ struct MissingFeatures { static bool opCallABIIndirectArg() { return false; } static bool opCallWidenArg() { return false; } static bool opCallBitcastArg() { return false; } - static bool opCallImplicitObjectSizeArgs() { return false; } static bool opCallReturn() { return false; } static bool opCallArgEvaluationOrder() { return false; } static bool opCallCallConv() { return false; } diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp index 62729839b6ae4..8e0410e7a1548 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp @@ -2583,6 +2583,10 @@ mlir::Value CIRGenFunction::emitVAArg(VAArgExpr *ve) { /// Checks if using the result of __builtin_object_size(p, @p from) in place of /// __builtin_object_size(p, @p to) is correct. +/// +/// type=0 is the maximum object size; compatible with type=1 (maximum of the +/// remaining bytes, which is always <= total size). type=3 is the minimum +/// remaining bytes; compatible with type=2 (minimum object size). static bool areBOSTypesCompatible(int from, int to) { return from == to || (from == 0 && to == 1) || (from == 3 && to == 2); } diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp b/clang/lib/CIR/CodeGen/CIRGenCall.cpp index dc074491b4582..7cf8157b44fda 100644 --- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp @@ -722,13 +722,15 @@ static void appendParameterTypes(const CIRGenTypes &cgt, return; } + // In the vast majority of cases, we'll have precisely FPT->getNumParams() + // parameters; the only thing that can change this is the presence of + // pass_object_size. So, we preallocate for the common case. prefix.reserve(prefix.size() + fpt->getNumParams()); auto extInfos = fpt->getExtParameterInfos(); for (unsigned i = 0, e = fpt->getNumParams(); i != e; ++i) { prefix.push_back(fpt->getParamType(i)); if (extInfos[i].hasPassObjectSize()) - prefix.push_back(cgt.getASTContext().getCanonicalType( - cgt.getASTContext().getSizeType())); + prefix.push_back(cgt.getASTContext().getCanonicalSizeType()); } } @@ -809,7 +811,6 @@ arrangeCIRFunctionInfo(CIRGenTypes &cgt, bool instanceMethod, assert(!cir::MissingFeatures::opCallFnInfoOpts()); RequiredArgs required = RequiredArgs::getFromProtoWithExtraSlots(fpt, prefix.size()); - assert(!cir::MissingFeatures::opCallExtParameterInfo()); appendParameterTypes(cgt, prefix, fpt); CanQualType resultType = fpt->getReturnType().getUnqualifiedType(); return cgt.arrangeCIRFunctionInfo(resultType, instanceMethod, prefix, @@ -934,7 +935,6 @@ const CIRGenFunctionInfo &CIRGenTypes::arrangeCXXConstructorCall( const CIRGenFunctionInfo &CIRGenTypes::arrangeCXXMethodCall( const CallArgList &args, const FunctionProtoType *proto, RequiredArgs required, unsigned numPrefixArgs) { - assert(!cir::MissingFeatures::opCallExtParameterInfo()); assert(numPrefixArgs + 1 <= args.size() && "Emitting a call with less args than the required prefix?"); @@ -1408,10 +1408,11 @@ void CIRGenFunction::emitCallArgs( return; QualType sizeTy = getContext().getSizeType(); - auto t = cast<cir::IntType>(cgm.sizeTy); + auto cirSizeTy = cast<cir::IntType>(cgm.sizeTy); assert(emittedArg.getValue() && "We emitted nothing for the arg?"); mlir::Value v = evaluateOrEmitBuiltinObjectSize( - arg, ps->getType(), t, emittedArg.getValue(), ps->isDynamic()); + arg, ps->getType(), cirSizeTy, emittedArg.getValue(), + ps->isDynamic()); args.add(RValue::get(v), sizeTy); if (!leftToRight) std::swap(args.back(), *(&args.back() - 1)); >From b857578d0adb3a221c17f159a67c32e42644503b Mon Sep 17 00:00:00 2001 From: Adam Smith <[email protected]> Date: Wed, 15 Apr 2026 11:58:49 -0700 Subject: [PATCH 3/3] [CIR] Address review feedback on pass_object_size - Use named BOSType enum constants instead of raw 0/1/2/3 - Use structured bindings for map find results - Revert unrelated formatting change on comment - Fix comment case: fpt not FPT - Use explicit type for getExtParameterInfos() return - Inline cast<cir::IntType> instead of intermediate variable - Remove SmallDenseMap size parameter - Rename sizeArguments -> objectSizeArguments Made-with: Cursor --- clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 31 +++++++++++++++++------- clang/lib/CIR/CodeGen/CIRGenCall.cpp | 17 ++++++------- clang/lib/CIR/CodeGen/CIRGenFunction.cpp | 5 ++-- clang/lib/CIR/CodeGen/CIRGenFunction.h | 4 +-- 4 files changed, 34 insertions(+), 23 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp index 8e0410e7a1548..9efa467cb2abc 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp @@ -2581,14 +2581,26 @@ mlir::Value CIRGenFunction::emitVAArg(VAArgExpr *ve) { return cir::VAArgOp::create(builder, loc, type, vaList); } +/// __builtin_object_size type constants. +enum BOSType { + BOSMaxTotalSize = 0, // max total object size + BOSMaxRemainingSize = 1, // max remaining bytes in sub-object + BOSMinTotalSize = 2, // min total object size + BOSMinRemainingSize = 3 // min remaining bytes in sub-object +}; + /// Checks if using the result of __builtin_object_size(p, @p from) in place of /// __builtin_object_size(p, @p to) is correct. -/// -/// type=0 is the maximum object size; compatible with type=1 (maximum of the -/// remaining bytes, which is always <= total size). type=3 is the minimum -/// remaining bytes; compatible with type=2 (minimum object size). static bool areBOSTypesCompatible(int from, int to) { - return from == to || (from == 0 && to == 1) || (from == 3 && to == 2); + if (from == to) + return true; + // Max total size subsumes max remaining size. + if (from == BOSMaxTotalSize && to == BOSMaxRemainingSize) + return true; + // Min remaining size subsumes min total size. + if (from == BOSMinRemainingSize && to == BOSMinTotalSize) + return true; + return false; } mlir::Value CIRGenFunction::emitBuiltinObjectSize(const Expr *e, unsigned type, @@ -2600,14 +2612,15 @@ mlir::Value CIRGenFunction::emitBuiltinObjectSize(const Expr *e, unsigned type, auto *param = dyn_cast<ParmVarDecl>(d->getDecl()); auto *ps = d->getDecl()->getAttr<PassObjectSizeAttr>(); if (param && ps && areBOSTypesCompatible(ps->getType(), type)) { - auto iter = sizeArguments.find(param); - assert(iter != sizeArguments.end()); + auto iter = objectSizeArguments.find(param); + assert(iter != objectSizeArguments.end()); + auto &[paramDecl, sizeDecl] = *iter; - const ImplicitParamDecl *sizeDecl = iter->second; auto dIter = localDeclMap.find(sizeDecl); assert(dIter != localDeclMap.end()); + auto &[implDecl, sizeAddr] = *dIter; - return emitLoadOfScalar(dIter->second, /*volatile=*/false, + return emitLoadOfScalar(sizeAddr, /*volatile=*/false, getContext().getSizeType(), e->getBeginLoc(), LValueBaseInfo(AlignmentSource::Decl)); } diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp b/clang/lib/CIR/CodeGen/CIRGenCall.cpp index 7cf8157b44fda..af24200a48650 100644 --- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp @@ -710,8 +710,8 @@ static CanQual<FunctionProtoType> getFormalType(const CXXMethodDecl *md) { .getAs<FunctionProtoType>(); } -/// Adds the formal parameters in FPT to the given prefix. If any parameter in -/// FPT has pass_object_size attrs, then we'll add parameters for those, too. +/// Adds the formal parameters in FPT to the given prefix. If any parameter in +/// FPT has pass_object_size_attrs, then we'll add parameters for those, too. /// TODO(cir): this should be shared with LLVM codegen static void appendParameterTypes(const CIRGenTypes &cgt, SmallVectorImpl<CanQualType> &prefix, @@ -722,11 +722,12 @@ static void appendParameterTypes(const CIRGenTypes &cgt, return; } - // In the vast majority of cases, we'll have precisely FPT->getNumParams() + // In the vast majority of cases, we'll have precisely fpt->getNumParams() // parameters; the only thing that can change this is the presence of // pass_object_size. So, we preallocate for the common case. prefix.reserve(prefix.size() + fpt->getNumParams()); - auto extInfos = fpt->getExtParameterInfos(); + ArrayRef<FunctionProtoType::ExtParameterInfo> extInfos = + fpt->getExtParameterInfos(); for (unsigned i = 0, e = fpt->getNumParams(); i != e; ++i) { prefix.push_back(fpt->getParamType(i)); if (extInfos[i].hasPassObjectSize()) @@ -871,8 +872,7 @@ arrangeFreeFunctionLikeCall(CIRGenTypes &cgt, CIRGenModule &cgm, if (info.hasPassObjectSize()) ++numExtraSlots; if (proto->isVariadic()) - required = - RequiredArgs::getFromProtoWithExtraSlots(proto, numExtraSlots); + required = RequiredArgs::getFromProtoWithExtraSlots(proto, numExtraSlots); } else if (cgm.getTargetCIRGenInfo().isNoProtoCallVariadic( cast<FunctionNoProtoType>(fnType))) cgm.errorNYI("call to function without a prototype"); @@ -1408,11 +1408,10 @@ void CIRGenFunction::emitCallArgs( return; QualType sizeTy = getContext().getSizeType(); - auto cirSizeTy = cast<cir::IntType>(cgm.sizeTy); assert(emittedArg.getValue() && "We emitted nothing for the arg?"); mlir::Value v = evaluateOrEmitBuiltinObjectSize( - arg, ps->getType(), cirSizeTy, emittedArg.getValue(), - ps->isDynamic()); + arg, ps->getType(), cast<cir::IntType>(cgm.sizeTy), + emittedArg.getValue(), ps->isDynamic()); args.add(RValue::get(v), sizeTy); if (!leftToRight) std::swap(args.back(), *(&args.back() - 1)); diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp index 263641fe0023f..5e020f1913225 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp @@ -1004,9 +1004,8 @@ clang::QualType CIRGenFunction::buildFunctionArgList(clang::GlobalDecl gd, auto *implicit = ImplicitParamDecl::Create( getContext(), param->getDeclContext(), param->getLocation(), - /*Id=*/nullptr, getContext().getSizeType(), - ImplicitParamKind::Other); - sizeArguments[param] = implicit; + /*Id=*/nullptr, getContext().getSizeType(), ImplicitParamKind::Other); + objectSizeArguments[param] = implicit; args.push_back(implicit); } } diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h index 5cfde7ac18066..7cbd901a6511e 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.h +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h @@ -176,8 +176,8 @@ class CIRGenFunction : public CIRGenTypeCache { /// If a ParmVarDecl had the pass_object_size attribute, this will contain a /// mapping from said ParmVarDecl to its implicit "object_size" parameter. - llvm::SmallDenseMap<const ParmVarDecl *, const ImplicitParamDecl *, 2> - sizeArguments; + llvm::SmallDenseMap<const ParmVarDecl *, const ImplicitParamDecl *> + objectSizeArguments; /// The value of 'this' to sue when evaluating CXXDefaultInitExprs within this /// expression. _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
