Skip to content

Commit 88c3825

Browse files
authored
[CIR] Add support for constructors with VTT parameters (#156521)
This adds the support for implicit VTT arguments in constructors.
1 parent a862225 commit 88c3825

17 files changed

+852
-40
lines changed

clang/include/clang/CIR/MissingFeatures.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -132,10 +132,8 @@ struct MissingFeatures {
132132
// RecordType
133133
static bool skippedLayout() { return false; }
134134
static bool astRecordDeclAttr() { return false; }
135-
static bool cxxSupport() { return false; }
136135
static bool recordZeroInit() { return false; }
137136
static bool zeroSizeRecordMembers() { return false; }
138-
static bool recordLayoutVirtualBases() { return false; }
139137

140138
// Various handling of deferred processing in CIRGenModule.
141139
static bool cgmRelease() { return false; }
@@ -148,7 +146,6 @@ struct MissingFeatures {
148146
static bool cxxabiUseARMMethodPtrABI() { return false; }
149147
static bool cxxabiUseARMGuardVarABI() { return false; }
150148
static bool cxxabiAppleARM64CXXABI() { return false; }
151-
static bool cxxabiStructorImplicitParam() { return false; }
152149
static bool isDiscreteBitFieldABI() { return false; }
153150

154151
// Address class
@@ -230,7 +227,6 @@ struct MissingFeatures {
230227
static bool globalViewIndices() { return false; }
231228
static bool globalViewIntLowering() { return false; }
232229
static bool hip() { return false; }
233-
static bool implicitConstructorArgs() { return false; }
234230
static bool incrementProfileCounter() { return false; }
235231
static bool innermostEHScope() { return false; }
236232
static bool insertBuiltinUnpredictable() { return false; }

clang/lib/CIR/CodeGen/CIRGenBuilder.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,10 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
287287
cir::ConstantOp getUInt32(uint32_t c, mlir::Location loc) {
288288
return getConstantInt(loc, getUInt32Ty(), c);
289289
}
290+
cir::ConstantOp getSInt64(uint64_t c, mlir::Location loc) {
291+
cir::IntType sInt64Ty = getSInt64Ty();
292+
return cir::ConstantOp::create(*this, loc, cir::IntAttr::get(sInt64Ty, c));
293+
}
290294

291295
// Creates constant nullptr for pointer type ty.
292296
cir::ConstantOp getNullPtr(mlir::Type ty, mlir::Location loc) {
@@ -359,6 +363,18 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
359363
return Address(baseAddr, destType, addr.getAlignment());
360364
}
361365

366+
mlir::Value createVTTAddrPoint(mlir::Location loc, mlir::Type retTy,
367+
mlir::Value addr, uint64_t offset) {
368+
return cir::VTTAddrPointOp::create(*this, loc, retTy,
369+
mlir::FlatSymbolRefAttr{}, addr, offset);
370+
}
371+
372+
mlir::Value createVTTAddrPoint(mlir::Location loc, mlir::Type retTy,
373+
mlir::FlatSymbolRefAttr sym, uint64_t offset) {
374+
return cir::VTTAddrPointOp::create(*this, loc, retTy, sym, mlir::Value{},
375+
offset);
376+
}
377+
362378
/// Cast the element type of the given address to a different type,
363379
/// preserving information like the alignment.
364380
Address createElementBitCast(mlir::Location loc, Address addr,
@@ -379,6 +395,23 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
379395
/*mem_order=*/cir::MemOrderAttr{});
380396
}
381397

398+
cir::LoadOp createAlignedLoad(mlir::Location loc, mlir::Type ty,
399+
mlir::Value ptr, llvm::MaybeAlign align) {
400+
if (ty != mlir::cast<cir::PointerType>(ptr.getType()).getPointee())
401+
ptr = createPtrBitcast(ptr, ty);
402+
uint64_t alignment = align ? align->value() : 0;
403+
mlir::IntegerAttr alignAttr = getAlignmentAttr(alignment);
404+
return cir::LoadOp::create(*this, loc, ptr, /*isDeref=*/false,
405+
/*isVolatile=*/false, alignAttr,
406+
/*mem_order=*/cir::MemOrderAttr{});
407+
}
408+
409+
cir::LoadOp
410+
createAlignedLoad(mlir::Location loc, mlir::Type ty, mlir::Value ptr,
411+
clang::CharUnits align = clang::CharUnits::One()) {
412+
return createAlignedLoad(loc, ty, ptr, align.getAsAlign());
413+
}
414+
382415
cir::StoreOp createStore(mlir::Location loc, mlir::Value val, Address dst,
383416
bool isVolatile = false,
384417
mlir::IntegerAttr align = {},

clang/lib/CIR/CodeGen/CIRGenCXXABI.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,20 @@ using namespace clang::CIRGen;
2222

2323
CIRGenCXXABI::~CIRGenCXXABI() {}
2424

25+
CIRGenCXXABI::AddedStructorArgCounts CIRGenCXXABI::addImplicitConstructorArgs(
26+
CIRGenFunction &cgf, const CXXConstructorDecl *d, CXXCtorType type,
27+
bool forVirtualBase, bool delegating, CallArgList &args) {
28+
AddedStructorArgs addedArgs =
29+
getImplicitConstructorArgs(cgf, d, type, forVirtualBase, delegating);
30+
for (auto [idx, prefixArg] : llvm::enumerate(addedArgs.prefix))
31+
args.insert(args.begin() + 1 + idx,
32+
CallArg(RValue::get(prefixArg.value), prefixArg.type));
33+
for (const auto &arg : addedArgs.suffix)
34+
args.add(RValue::get(arg.value), arg.type);
35+
return AddedStructorArgCounts(addedArgs.prefix.size(),
36+
addedArgs.suffix.size());
37+
}
38+
2539
void CIRGenCXXABI::buildThisParam(CIRGenFunction &cgf,
2640
FunctionArgList &params) {
2741
const auto *md = cast<CXXMethodDecl>(cgf.curGD.getDecl());

clang/lib/CIR/CodeGen/CIRGenCXXABI.h

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,67 @@ class CIRGenCXXABI {
4747
/// constructor/destructor Decl.
4848
virtual void emitCXXStructor(clang::GlobalDecl gd) = 0;
4949

50+
virtual mlir::Value
51+
getVirtualBaseClassOffset(mlir::Location loc, CIRGenFunction &cgf,
52+
Address thisAddr, const CXXRecordDecl *classDecl,
53+
const CXXRecordDecl *baseClassDecl) = 0;
54+
5055
public:
56+
/// Similar to AddedStructorArgs, but only notes the number of additional
57+
/// arguments.
58+
struct AddedStructorArgCounts {
59+
unsigned prefix = 0;
60+
unsigned suffix = 0;
61+
AddedStructorArgCounts() = default;
62+
AddedStructorArgCounts(unsigned p, unsigned s) : prefix(p), suffix(s) {}
63+
static AddedStructorArgCounts withPrefix(unsigned n) { return {n, 0}; }
64+
static AddedStructorArgCounts withSuffix(unsigned n) { return {0, n}; }
65+
};
66+
67+
/// Additional implicit arguments to add to the beginning (Prefix) and end
68+
/// (Suffix) of a constructor / destructor arg list.
69+
///
70+
/// Note that Prefix should actually be inserted *after* the first existing
71+
/// arg; `this` arguments always come first.
72+
struct AddedStructorArgs {
73+
struct Arg {
74+
mlir::Value value;
75+
QualType type;
76+
};
77+
llvm::SmallVector<Arg, 1> prefix;
78+
llvm::SmallVector<Arg, 1> suffix;
79+
AddedStructorArgs() = default;
80+
AddedStructorArgs(llvm::SmallVector<Arg, 1> p, llvm::SmallVector<Arg, 1> s)
81+
: prefix(std::move(p)), suffix(std::move(s)) {}
82+
static AddedStructorArgs withPrefix(llvm::SmallVector<Arg, 1> args) {
83+
return {std::move(args), {}};
84+
}
85+
static AddedStructorArgs withSuffix(llvm::SmallVector<Arg, 1> args) {
86+
return {{}, std::move(args)};
87+
}
88+
};
89+
90+
/// Build the signature of the given constructor or destructor vairant by
91+
/// adding any required parameters. For convenience, ArgTys has been
92+
/// initialized with the type of 'this'.
93+
virtual AddedStructorArgCounts
94+
buildStructorSignature(GlobalDecl gd,
95+
llvm::SmallVectorImpl<CanQualType> &argTys) = 0;
96+
97+
AddedStructorArgCounts
98+
addImplicitConstructorArgs(CIRGenFunction &cgf, const CXXConstructorDecl *d,
99+
CXXCtorType type, bool forVirtualBase,
100+
bool delegating, CallArgList &args);
101+
51102
clang::ImplicitParamDecl *getThisDecl(CIRGenFunction &cgf) {
52103
return cgf.cxxabiThisDecl;
53104
}
54105

106+
virtual AddedStructorArgs
107+
getImplicitConstructorArgs(CIRGenFunction &cgf, const CXXConstructorDecl *d,
108+
CXXCtorType type, bool forVirtualBase,
109+
bool delegating) = 0;
110+
55111
/// Emit the ABI-specific prolog for the function
56112
virtual void emitInstanceFunctionProlog(SourceLocation loc,
57113
CIRGenFunction &cgf) = 0;
@@ -144,6 +200,17 @@ class CIRGenCXXABI {
144200
CIRGenFunction &cgf, const CXXRecordDecl *vtableClass, BaseSubobject base,
145201
const CXXRecordDecl *nearestVBase) = 0;
146202

203+
/// Insert any ABI-specific implicit parameters into the parameter list for a
204+
/// function. This generally involves extra data for constructors and
205+
/// destructors.
206+
///
207+
/// ABIs may also choose to override the return type, which has been
208+
/// initialized with the type of 'this' if HasThisReturn(CGF.CurGD) is true or
209+
/// the formal return type of the function otherwise.
210+
virtual void addImplicitStructorParams(CIRGenFunction &cgf,
211+
clang::QualType &resTy,
212+
FunctionArgList &params) = 0;
213+
147214
/// Checks if ABI requires to initialize vptrs for given dynamic class.
148215
virtual bool
149216
doStructorsInitializeVPtrs(const clang::CXXRecordDecl *vtableClass) = 0;
@@ -162,6 +229,18 @@ class CIRGenCXXABI {
162229

163230
/// Gets the mangle context.
164231
clang::MangleContext &getMangleContext() { return *mangleContext; }
232+
233+
clang::ImplicitParamDecl *&getStructorImplicitParamDecl(CIRGenFunction &cgf) {
234+
return cgf.cxxStructorImplicitParamDecl;
235+
}
236+
237+
mlir::Value getStructorImplicitParamValue(CIRGenFunction &cgf) {
238+
return cgf.cxxStructorImplicitParamValue;
239+
}
240+
241+
void setStructorImplicitParamValue(CIRGenFunction &cgf, mlir::Value val) {
242+
cgf.cxxStructorImplicitParamValue = val;
243+
}
165244
};
166245

167246
/// Creates and Itanium-family ABI

clang/lib/CIR/CodeGen/CIRGenCall.cpp

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,10 @@ CIRGenTypes::arrangeCXXStructorDeclaration(GlobalDecl gd) {
197197
if (passParams)
198198
appendParameterTypes(*this, argTypes, fpt);
199199

200-
assert(!cir::MissingFeatures::implicitConstructorArgs());
200+
// The structor signature may include implicit parameters.
201+
[[maybe_unused]] CIRGenCXXABI::AddedStructorArgCounts addedArgs =
202+
theCXXABI.buildStructorSignature(gd, argTypes);
203+
assert(!cir::MissingFeatures::opCallCIRGenFuncInfoExtParamInfo());
201204

202205
RequiredArgs required =
203206
(passParams && md->isVariadic() ? RequiredArgs(argTypes.size())
@@ -324,26 +327,27 @@ arrangeFreeFunctionLikeCall(CIRGenTypes &cgt, CIRGenModule &cgm,
324327

325328
/// Arrange a call to a C++ method, passing the given arguments.
326329
///
330+
/// extraPrefixArgs is the number of ABI-specific args passed after the `this`
331+
/// parameter.
327332
/// passProtoArgs indicates whether `args` has args for the parameters in the
328333
/// given CXXConstructorDecl.
329334
const CIRGenFunctionInfo &CIRGenTypes::arrangeCXXConstructorCall(
330335
const CallArgList &args, const CXXConstructorDecl *d, CXXCtorType ctorKind,
331-
bool passProtoArgs) {
336+
unsigned extraPrefixArgs, unsigned extraSuffixArgs, bool passProtoArgs) {
332337

333338
// FIXME: Kill copy.
334339
llvm::SmallVector<CanQualType, 16> argTypes;
335340
for (const auto &arg : args)
336341
argTypes.push_back(astContext.getCanonicalParamType(arg.ty));
337342

338-
assert(!cir::MissingFeatures::implicitConstructorArgs());
339343
// +1 for implicit this, which should always be args[0]
340-
unsigned totalPrefixArgs = 1;
344+
unsigned totalPrefixArgs = 1 + extraPrefixArgs;
341345

342346
CanQual<FunctionProtoType> fpt = getFormalType(d);
343-
RequiredArgs required =
344-
passProtoArgs
345-
? RequiredArgs::getFromProtoWithExtraSlots(fpt, totalPrefixArgs)
346-
: RequiredArgs::All;
347+
RequiredArgs required = passProtoArgs
348+
? RequiredArgs::getFromProtoWithExtraSlots(
349+
fpt, totalPrefixArgs + extraSuffixArgs)
350+
: RequiredArgs::All;
347351

348352
GlobalDecl gd(d, ctorKind);
349353
if (theCXXABI.hasThisReturn(gd))

0 commit comments

Comments
 (0)