Skip to content

Commit 449afd4

Browse files
committed
Merge branch 'main' of https://github.com/llvm/llvm-project
2 parents ef4c290 + 54f53c9 commit 449afd4

File tree

23 files changed

+1253
-60
lines changed

23 files changed

+1253
-60
lines changed

clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,13 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
212212
return create<cir::AllocaOp>(loc, addrType, type, name, alignment);
213213
}
214214

215+
/// Get constant address of a global variable as an MLIR attribute.
216+
cir::GlobalViewAttr getGlobalViewAttr(cir::PointerType type,
217+
cir::GlobalOp globalOp) {
218+
auto symbol = mlir::FlatSymbolRefAttr::get(globalOp.getSymNameAttr());
219+
return cir::GlobalViewAttr::get(type, symbol);
220+
}
221+
215222
mlir::Value createGetGlobal(mlir::Location loc, cir::GlobalOp global) {
216223
assert(!cir::MissingFeatures::addressSpace());
217224
return create<cir::GetGlobalOp>(loc, getPointerTo(global.getSymType()),

clang/include/clang/CIR/Dialect/IR/CIRAttrs.td

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,53 @@ def CIR_ConstPtrAttr : CIR_Attr<"ConstPtr", "ptr", [TypedAttrInterface]> {
370370
}];
371371
}
372372

373+
//===----------------------------------------------------------------------===//
374+
// GlobalViewAttr
375+
//===----------------------------------------------------------------------===//
376+
377+
def CIR_GlobalViewAttr : CIR_Attr<"GlobalView", "global_view", [
378+
TypedAttrInterface
379+
]> {
380+
let summary = "Provides constant access to a global address";
381+
let description = [{
382+
Get constant address of global `symbol`. It provides a way to access globals
383+
from other global and always produces a pointer.
384+
385+
The type of the input symbol can be different from `#cir.global_view`
386+
output type, since a given view of the global might require a static
387+
cast for initializing other globals.
388+
389+
The result type of this attribute may be an integer type. In such a case,
390+
the pointer to the referenced global is casted to an integer and this
391+
attribute represents the casted result.
392+
393+
Example:
394+
395+
```
396+
cir.global external @s = @".str2": !cir.ptr<i8>
397+
cir.global external @x = #cir.global_view<@s> : !cir.ptr<i8>
398+
cir.global external @s_addr = #cir.global_view<@s> : !s64i
399+
```
400+
}];
401+
402+
let parameters = (ins AttributeSelfTypeParameter<"">:$type,
403+
"mlir::FlatSymbolRefAttr":$symbol);
404+
405+
let builders = [
406+
AttrBuilderWithInferredContext<(ins "mlir::Type":$type,
407+
"mlir::FlatSymbolRefAttr":$symbol), [{
408+
return $_get(type.getContext(), type, symbol);
409+
}]>
410+
];
411+
412+
// let genVerifyDecl = 1;
413+
let assemblyFormat = [{
414+
`<`
415+
$symbol
416+
`>`
417+
}];
418+
}
419+
373420
//===----------------------------------------------------------------------===//
374421
// ConstComplexAttr
375422
//===----------------------------------------------------------------------===//

clang/include/clang/CIR/MissingFeatures.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ struct MissingFeatures {
192192
static bool constantFoldSwitchStatement() { return false; }
193193
static bool constructABIArgDirectExtend() { return false; }
194194
static bool coverageMapping() { return false; }
195+
static bool createInvariantGroup() { return false; }
195196
static bool createProfileWeightsForLoop() { return false; }
196197
static bool ctorMemcpyizer() { return false; }
197198
static bool cudaSupport() { return false; }
@@ -200,6 +201,8 @@ struct MissingFeatures {
200201
static bool deferredCXXGlobalInit() { return false; }
201202
static bool ehCleanupFlags() { return false; }
202203
static bool ehCleanupScope() { return false; }
204+
static bool ehCleanupScopeRequiresEHCleanup() { return false; }
205+
static bool ehCleanupBranchFixups() { return false; }
203206
static bool ehstackBranches() { return false; }
204207
static bool emitCheckedInBoundsGEP() { return false; }
205208
static bool emitCondLikelihoodViaExpectIntrinsic() { return false; }
@@ -210,9 +213,12 @@ struct MissingFeatures {
210213
static bool fastMathFlags() { return false; }
211214
static bool fpConstraints() { return false; }
212215
static bool generateDebugInfo() { return false; }
216+
static bool globalViewIndices() { return false; }
217+
static bool globalViewIntLowering() { return false; }
213218
static bool hip() { return false; }
214219
static bool implicitConstructorArgs() { return false; }
215220
static bool incrementProfileCounter() { return false; }
221+
static bool innermostEHScope() { return false; }
216222
static bool insertBuiltinUnpredictable() { return false; }
217223
static bool instrumentation() { return false; }
218224
static bool intrinsics() { return false; }
@@ -233,7 +239,6 @@ struct MissingFeatures {
233239
static bool objCGC() { return false; }
234240
static bool objCLifetime() { return false; }
235241
static bool openMP() { return false; }
236-
static bool opGlobalViewAttr() { return false; }
237242
static bool opTBAA() { return false; }
238243
static bool peepholeProtection() { return false; }
239244
static bool pgoUse() { return false; }
@@ -260,6 +265,7 @@ struct MissingFeatures {
260265
static bool appleKext() { return false; }
261266
static bool dtorCleanups() { return false; }
262267
static bool vtableInitialization() { return false; }
268+
static bool vtableRelativeLayout() { return false; }
263269
static bool msvcBuiltins() { return false; }
264270
static bool vlas() { return false; }
265271

clang/lib/CIR/CodeGen/CIRGenBuilder.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,17 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
244244
}
245245
bool isInt(mlir::Type i) { return mlir::isa<cir::IntType>(i); }
246246

247+
// Fetch the type representing a pointer to unsigned int8 values.
248+
cir::PointerType getUInt8PtrTy() { return typeCache.UInt8PtrTy; }
249+
250+
/// Get a CIR anonymous record type.
251+
cir::RecordType getAnonRecordTy(llvm::ArrayRef<mlir::Type> members,
252+
bool packed = false, bool padded = false) {
253+
assert(!cir::MissingFeatures::astRecordDeclAttr());
254+
auto kind = cir::RecordType::RecordKind::Struct;
255+
return getType<cir::RecordType>(members, packed, padded, kind);
256+
}
257+
247258
//
248259
// Constant creation helpers
249260
// -------------------------

clang/lib/CIR/CodeGen/CIRGenCXXABI.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,11 @@ class CIRGenCXXABI {
8080
bool forVirtualBase, bool delegating,
8181
Address thisAddr, QualType thisTy) = 0;
8282

83+
/// Checks if ABI requires extra virtual offset for vtable field.
84+
virtual bool
85+
isVirtualOffsetNeededForVTableField(CIRGenFunction &cgf,
86+
CIRGenFunction::VPtr vptr) = 0;
87+
8388
/// Returns true if the given destructor type should be emitted as a linkonce
8489
/// delegating thunk, regardless of whether the dtor is defined in this TU or
8590
/// not.
@@ -90,6 +95,26 @@ class CIRGenCXXABI {
9095
getCXXDestructorLinkage(GVALinkage linkage, const CXXDestructorDecl *dtor,
9196
CXXDtorType dt) const;
9297

98+
/// Get the address of the vtable for the given record decl which should be
99+
/// used for the vptr at the given offset in RD.
100+
virtual cir::GlobalOp getAddrOfVTable(const CXXRecordDecl *rd,
101+
CharUnits vptrOffset) = 0;
102+
103+
/// Get the address point of the vtable for the given base subobject.
104+
virtual mlir::Value
105+
getVTableAddressPoint(BaseSubobject base,
106+
const CXXRecordDecl *vtableClass) = 0;
107+
108+
/// Get the address point of the vtable for the given base subobject while
109+
/// building a constructor or a destructor.
110+
virtual mlir::Value getVTableAddressPointInStructor(
111+
CIRGenFunction &cgf, const CXXRecordDecl *vtableClass, BaseSubobject base,
112+
const CXXRecordDecl *nearestVBase) = 0;
113+
114+
/// Checks if ABI requires to initialize vptrs for given dynamic class.
115+
virtual bool
116+
doStructorsInitializeVPtrs(const clang::CXXRecordDecl *vtableClass) = 0;
117+
93118
/// Returns true if the given constructor or destructor is one of the kinds
94119
/// that the ABI says returns 'this' (only applies when called non-virtually
95120
/// for destructors).

clang/lib/CIR/CodeGen/CIRGenClass.cpp

Lines changed: 92 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -199,10 +199,6 @@ void CIRGenFunction::emitCtorPrologue(const CXXConstructorDecl *cd,
199199
return;
200200
}
201201

202-
// If there are no member initializers, we can just return.
203-
if (cd->getNumCtorInitializers() == 0)
204-
return;
205-
206202
const CXXRecordDecl *classDecl = cd->getParent();
207203

208204
// This code doesn't use range-based iteration because we may need to emit
@@ -227,7 +223,8 @@ void CIRGenFunction::emitCtorPrologue(const CXXConstructorDecl *cd,
227223
}
228224

229225
const mlir::Value oldThisValue = cxxThisValue;
230-
if (!constructVBases && (*b)->isBaseInitializer() && (*b)->isBaseVirtual()) {
226+
if (!constructVBases && b != e && (*b)->isBaseInitializer() &&
227+
(*b)->isBaseVirtual()) {
231228
cgm.errorNYI(cd->getSourceRange(),
232229
"emitCtorPrologue: virtual base initializer");
233230
return;
@@ -249,11 +246,7 @@ void CIRGenFunction::emitCtorPrologue(const CXXConstructorDecl *cd,
249246

250247
cxxThisValue = oldThisValue;
251248

252-
if (classDecl->isDynamicClass()) {
253-
cgm.errorNYI(cd->getSourceRange(),
254-
"emitCtorPrologue: initialize vtable pointers");
255-
return;
256-
}
249+
initializeVTablePointers(getLoc(cd->getBeginLoc()), classDecl);
257250

258251
// Finally, initialize class members.
259252
FieldConstructionScope fcs(*this, loadCXXThisAddress());
@@ -271,6 +264,95 @@ void CIRGenFunction::emitCtorPrologue(const CXXConstructorDecl *cd,
271264
}
272265
}
273266

267+
void CIRGenFunction::initializeVTablePointer(mlir::Location loc,
268+
const VPtr &vptr) {
269+
// Compute the address point.
270+
mlir::Value vtableAddressPoint =
271+
cgm.getCXXABI().getVTableAddressPointInStructor(
272+
*this, vptr.vtableClass, vptr.base, vptr.nearestVBase);
273+
274+
if (!vtableAddressPoint)
275+
return;
276+
277+
// Compute where to store the address point.
278+
mlir::Value virtualOffset{};
279+
CharUnits nonVirtualOffset = CharUnits::Zero();
280+
281+
mlir::Type baseValueTy;
282+
if (cgm.getCXXABI().isVirtualOffsetNeededForVTableField(*this, vptr)) {
283+
cgm.errorNYI(loc, "initializeVTablePointer: virtual offset for vtable");
284+
} else {
285+
// We can just use the base offset in the complete class.
286+
nonVirtualOffset = vptr.base.getBaseOffset();
287+
baseValueTy = convertType(getContext().getTagDeclType(vptr.base.getBase()));
288+
}
289+
290+
// Apply the offsets.
291+
Address vtableField = loadCXXThisAddress();
292+
if (!nonVirtualOffset.isZero() || virtualOffset) {
293+
cgm.errorNYI(loc,
294+
"initializeVTablePointer: non-virtual and virtual offset");
295+
}
296+
297+
// Finally, store the address point. Use the same CIR types as the field.
298+
//
299+
// vtable field is derived from `this` pointer, therefore they should be in
300+
// the same addr space.
301+
assert(!cir::MissingFeatures::addressSpace());
302+
// TODO(cir): This should be cir.vtable.get_vptr.
303+
vtableField = builder.createElementBitCast(loc, vtableField,
304+
vtableAddressPoint.getType());
305+
builder.createStore(loc, vtableAddressPoint, vtableField);
306+
assert(!cir::MissingFeatures::opTBAA());
307+
assert(!cir::MissingFeatures::createInvariantGroup());
308+
}
309+
310+
void CIRGenFunction::initializeVTablePointers(mlir::Location loc,
311+
const CXXRecordDecl *rd) {
312+
// Ignore classes without a vtable.
313+
if (!rd->isDynamicClass())
314+
return;
315+
316+
// Initialize the vtable pointers for this class and all of its bases.
317+
if (cgm.getCXXABI().doStructorsInitializeVPtrs(rd))
318+
for (const auto &vptr : getVTablePointers(rd))
319+
initializeVTablePointer(loc, vptr);
320+
321+
if (rd->getNumVBases())
322+
cgm.errorNYI(loc, "initializeVTablePointers: virtual base");
323+
}
324+
325+
CIRGenFunction::VPtrsVector
326+
CIRGenFunction::getVTablePointers(const CXXRecordDecl *vtableClass) {
327+
CIRGenFunction::VPtrsVector vptrsResult;
328+
getVTablePointers(BaseSubobject(vtableClass, CharUnits::Zero()),
329+
/*NearestVBase=*/nullptr,
330+
/*OffsetFromNearestVBase=*/CharUnits::Zero(),
331+
/*BaseIsNonVirtualPrimaryBase=*/false, vtableClass,
332+
vptrsResult);
333+
return vptrsResult;
334+
}
335+
336+
void CIRGenFunction::getVTablePointers(BaseSubobject base,
337+
const CXXRecordDecl *nearestVBase,
338+
CharUnits offsetFromNearestVBase,
339+
bool baseIsNonVirtualPrimaryBase,
340+
const CXXRecordDecl *vtableClass,
341+
VPtrsVector &vptrs) {
342+
// If this base is a non-virtual primary base the address point has already
343+
// been set.
344+
if (!baseIsNonVirtualPrimaryBase) {
345+
// Initialize the vtable pointer for this base.
346+
VPtr vptr = {base, nearestVBase, offsetFromNearestVBase, vtableClass};
347+
vptrs.push_back(vptr);
348+
}
349+
350+
const CXXRecordDecl *rd = base.getBase();
351+
352+
if (rd->getNumBases())
353+
cgm.errorNYI(rd->getSourceRange(), "getVTablePointers: traverse bases");
354+
}
355+
274356
Address CIRGenFunction::loadCXXThisAddress() {
275357
assert(curFuncDecl && "loading 'this' without a func declaration?");
276358
assert(isa<CXXMethodDecl>(curFuncDecl));

0 commit comments

Comments
 (0)