Skip to content
Open
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
29 changes: 29 additions & 0 deletions clang/include/clang/CIR/Interfaces/CIROpInterfaces.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,33 @@ namespace cir {} // namespace cir

namespace cir {} // namespace cir

// Casting specializations for CIRGlobalValueInterface to concrete types.
// OpInterfaces don't support casting to concrete types with reference return
// types, so we specialize CastInfo to return by value instead.
namespace llvm {
template <typename To>
struct CastInfo<
To, cir::CIRGlobalValueInterface,
std::enable_if_t<!std::is_same<To, cir::CIRGlobalValueInterface>::value>> {
using CastReturnType = To;

static inline bool isPossible(cir::CIRGlobalValueInterface interface) {
return llvm::isa<To>(interface.getOperation());
}

static inline CastReturnType doCast(cir::CIRGlobalValueInterface interface) {
return llvm::cast<To>(interface.getOperation());
}

static inline CastReturnType castFailed() { return CastReturnType(nullptr); }

static inline CastReturnType
doCastIfPossible(cir::CIRGlobalValueInterface interface) {
if (!isPossible(interface))
return castFailed();
return doCast(interface);
}
};
} // namespace llvm

#endif // MLIR_INTERFACES_CIR_OP_H_
12 changes: 12 additions & 0 deletions clang/include/clang/CIR/Interfaces/CIROpInterfaces.td
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,18 @@ let cppNamespace = "::cir" in {
}]
>,
InterfaceMethod<"",
"void", "setGlobalVisibility", (ins "cir::VisibilityKind":$val), [{}],
/*defaultImplementation=*/[{
$_op.setGlobalVisibility(val);
}]
>,
InterfaceMethod<"",
"void", "setLinkage", (ins "cir::GlobalLinkageKind":$val), [{}],
/*defaultImplementation=*/[{
$_op.setLinkage(val);
}]
>,
InterfaceMethod<"",
"bool", "isDSOLocal", (ins), [{}],
/*defaultImplementation=*/[{
return $_op.getDsoLocal();
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/CIR/MissingFeatures.h
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ struct MissingFeatures {
// ABIInfo queries.
static bool useTargetLoweringABIInfo() { return false; }
static bool isEmptyFieldForLayout() { return false; }
static bool ABIArgInfo() { return false; }

// Misc
static bool cacheRecordLayouts() { return false; }
Expand Down Expand Up @@ -482,6 +483,8 @@ struct MissingFeatures {
static bool skipTempCopy() { return false; }

static bool dataLayoutPtrHandlingBasedOnLangAS() { return false; }

static bool tailCall() { return false; }
};

} // namespace cir
Expand Down
8 changes: 8 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenCXXABI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,11 @@ bool CIRGenCXXABI::requiresArrayCookie(const CXXNewExpr *E) {

return E->getAllocatedType().isDestructedType();
}

void CIRGenCXXABI::emitReturnFromThunk(CIRGenFunction &cgf, RValue rv,
QualType resultType) {
assert(!cgf.hasAggregateEvaluationKind(resultType) &&
"cannot handle aggregates");
auto loc = cgf.getBuilder().getUnknownLoc();
cgf.emitReturnOfRValue(loc, rv, resultType);
}
22 changes: 22 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenCXXABI.h
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,28 @@ class CIRGenCXXABI {
virtual void setThunkLinkage(cir::FuncOp Thunk, bool ForVTable, GlobalDecl GD,
bool ReturnAdjustment) = 0;

/// Perform adjustment on the this pointer for a thunk.
/// Returns the adjusted this pointer value.
virtual mlir::Value
performThisAdjustment(CIRGenFunction &cgf, Address thisAddr,
const CXXRecordDecl *unadjustedClass,
const ThunkInfo &ti) = 0;

/// Perform adjustment on a return pointer for a thunk (covariant returns).
/// Returns the adjusted return pointer value.
virtual mlir::Value
performReturnAdjustment(CIRGenFunction &cgf, Address ret,
const CXXRecordDecl *unadjustedClass,
const ReturnAdjustment &ra) = 0;

virtual void adjustCallArgsForDestructorThunk(CIRGenFunction &cgf,
GlobalDecl globalDecl,
CallArgList &callArgs) {}

/// Emit a return from a thunk.
virtual void emitReturnFromThunk(CIRGenFunction &cgf, RValue rv,
QualType resultType);

virtual mlir::Attribute getAddrOfRTTIDescriptor(mlir::Location loc,
QualType Ty) = 0;
virtual CatchTypeInfo
Expand Down
17 changes: 11 additions & 6 deletions clang/lib/CIR/CodeGen/CIRGenFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -765,8 +765,10 @@ cir::FuncOp CIRGenFunction::generateCode(clang::GlobalDecl gd, cir::FuncOp fn,
// Create a scope in the symbol table to hold variable declarations.
SymTableScopeTy varScope(symbolTable);
// Compiler synthetized functions might have invalid slocs...
auto bSrcLoc = fd->getBody()->getBeginLoc();
auto eSrcLoc = fd->getBody()->getEndLoc();
auto bSrcLoc =
(fd && fd->getBody()) ? fd->getBody()->getBeginLoc() : SourceLocation();
auto eSrcLoc =
(fd && fd->getBody()) ? fd->getBody()->getEndLoc() : SourceLocation();
auto unknownLoc = builder.getUnknownLoc();

auto fnBeginLoc = bSrcLoc.isValid() ? getLoc(bSrcLoc) : unknownLoc;
Expand Down Expand Up @@ -1158,11 +1160,11 @@ void CIRGenFunction::StartFunction(GlobalDecl gd, QualType retTy,
llvm_unreachable("NYI");

// Apply xray attributes to the function (as a string, for now)
if (d->getAttr<XRayInstrumentAttr>()) {
if (d && d->getAttr<XRayInstrumentAttr>()) {
assert(!cir::MissingFeatures::xray());
}

if (ShouldXRayInstrumentFunction()) {
if (d && ShouldXRayInstrumentFunction()) {
assert(!cir::MissingFeatures::xray());
}

Expand Down Expand Up @@ -1365,12 +1367,15 @@ void CIRGenFunction::StartFunction(GlobalDecl gd, QualType retTy,

// Location of the store to the param storage tracked as beginning of
// the function body.
auto fnBodyBegin = getLoc(fd->getBody()->getBeginLoc());
auto fnBodyBegin = (fd && fd->getBody())
? getLoc(fd->getBody()->getBeginLoc())
: getLoc(Loc);
builder.CIRBaseBuilderTy::createStore(fnBodyBegin, paramVal, addr);
}
assert(builder.getInsertionBlock() && "Should be valid");

auto fnEndLoc = getLoc(fd->getBody()->getEndLoc());
auto fnEndLoc = (fd && fd->getBody()) ? getLoc(fd->getBody()->getEndLoc())
: getLoc(Loc);

// When the current function is not void, create an address to store the
// result value.
Expand Down
18 changes: 18 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -2131,6 +2131,24 @@ class CIRGenFunction : public CIRGenTypeCache {

void emitDestructorBody(FunctionArgList &Args);

/// Generate a thunk for the given method.
void generateThunk(cir::FuncOp fn, const CIRGenFunctionInfo &fnInfo,
GlobalDecl gd, const ThunkInfo &thunk,
bool isUnprototyped);

void startThunk(cir::FuncOp fn, GlobalDecl gd,
const CIRGenFunctionInfo &fnInfo, bool isUnprototyped);

void emitCallAndReturnForThunk(cir::FuncOp callee, const ThunkInfo *thunk,
bool isUnprototyped);

/// Finish thunk generation.
void finishThunk();

/// Emit a musttail call for a thunk with a potentially adjusted this pointer.
void emitMustTailThunk(GlobalDecl gd, mlir::Value adjustedThisPtr,
cir::FuncOp callee);

mlir::LogicalResult emitDoStmt(const clang::DoStmt &S);

mlir::Value emitDynamicCast(Address ThisAddr, const CXXDynamicCastExpr *DCE);
Expand Down
68 changes: 67 additions & 1 deletion clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -239,10 +239,19 @@ class CIRGenItaniumCXXABI : public CIRGenCXXABI {
if (ForVTable && !Thunk.hasLocalLinkage())
Thunk.setLinkage(cir::GlobalLinkageKind::AvailableExternallyLinkage);
const auto *ND = cast<NamedDecl>(GD.getDecl());
CGM.setGVProperties(Thunk.getOperation(), ND);
CGM.setGVProperties(Thunk, ND);
}

bool exportThunk() override { return true; }

mlir::Value performThisAdjustment(CIRGenFunction &cgf, Address thisAddr,
const CXXRecordDecl *unadjustedClass,
const ThunkInfo &ti) override;

mlir::Value performReturnAdjustment(CIRGenFunction &cgf, Address ret,
const CXXRecordDecl *unadjustedClass,
const ReturnAdjustment &ra) override;

mlir::Attribute getAddrOfRTTIDescriptor(mlir::Location loc,
QualType Ty) override;
bool useThunkForDtorVariant(const CXXDestructorDecl *Dtor,
Expand Down Expand Up @@ -2144,6 +2153,63 @@ mlir::Attribute CIRGenItaniumCXXABI::getAddrOfRTTIDescriptor(mlir::Location loc,
return CIRGenItaniumRTTIBuilder(*this, CGM).BuildTypeInfo(loc, Ty);
}

static mlir::Value performTypeAdjustment(CIRGenFunction &cgf,
Address initialPtr,
const CXXRecordDecl *unadjustedClass,
int64_t nonVirtualAdjustment,
int64_t virtualAdjustment,
bool isReturnAdjustment) {
if (!nonVirtualAdjustment && !virtualAdjustment)
return initialPtr.getPointer();

auto &builder = cgf.getBuilder();
auto loc = builder.getUnknownLoc();
auto i8PtrTy = builder.getUInt8PtrTy();
mlir::Value v = builder.createBitcast(initialPtr.getPointer(), i8PtrTy);

// In a base-to-derived cast, the non-virtual adjustment is applied first.
if (nonVirtualAdjustment && !isReturnAdjustment) {
auto offsetConst = builder.getSInt64(nonVirtualAdjustment, loc);
v = builder.create<cir::PtrStrideOp>(loc, i8PtrTy, v, offsetConst);
}

// Perform the virtual adjustment if we have one.
mlir::Value resultPtr;
if (virtualAdjustment) {
llvm_unreachable("Virtual adjustment NYI - requires vtable offset lookup");
} else {
resultPtr = v;
}

// In a derived-to-base conversion, the non-virtual adjustment is
// applied second.
if (nonVirtualAdjustment && isReturnAdjustment) {
auto offsetConst = builder.getSInt64(nonVirtualAdjustment, loc);
resultPtr =
builder.create<cir::PtrStrideOp>(loc, i8PtrTy, resultPtr, offsetConst);
}

// Cast back to original pointer type
return builder.createBitcast(resultPtr, initialPtr.getType());
}

mlir::Value CIRGenItaniumCXXABI::performThisAdjustment(
CIRGenFunction &cgf, Address thisAddr, const CXXRecordDecl *unadjustedClass,
const ThunkInfo &ti) {
return performTypeAdjustment(cgf, thisAddr, unadjustedClass,
ti.This.NonVirtual,
ti.This.Virtual.Itanium.VCallOffsetOffset,
/*IsReturnAdjustment=*/false);
}

mlir::Value CIRGenItaniumCXXABI::performReturnAdjustment(
CIRGenFunction &cgf, Address ret, const CXXRecordDecl *unadjustedClass,
const ReturnAdjustment &ra) {
return performTypeAdjustment(cgf, ret, unadjustedClass, ra.NonVirtual,
ra.Virtual.Itanium.VBaseOffsetOffset,
/*IsReturnAdjustment=*/true);
}

void CIRGenItaniumCXXABI::emitVTableDefinitions(CIRGenVTables &CGVT,
const CXXRecordDecl *RD) {
auto VTable = getAddrOfVTable(RD, CharUnits());
Expand Down
Loading