Skip to content
Draft
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
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);
}
18 changes: 18 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenCXXABI.h
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,24 @@ 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;

/// 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
66 changes: 66 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,15 @@ class CIRGenItaniumCXXABI : public CIRGenCXXABI {
}

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
52 changes: 40 additions & 12 deletions clang/lib/CIR/CodeGen/CIRGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -826,14 +826,22 @@ cir::GlobalOp CIRGenModule::createGlobalOp(CIRGenModule &cgm,
// Some global emissions are triggered while emitting a function, e.g.
// void s() { const char *s = "yolo"; ... }
//
// Be sure to insert global before the current function
// Save the current function context for later insertion logic
auto *curCGF = cgm.getCurrCIRGenFun();
if (curCGF)
builder.setInsertionPoint(curCGF->CurFn);

// Clear insertion point to prevent auto-insertion by create()
// We'll manually insert at the correct location below
builder.clearInsertionPoint();

g = cir::GlobalOp::create(builder, loc, name, t, isConstant, linkage,
addrSpace);
if (!curCGF) {

// Manually insert at the correct location
if (curCGF) {
// Insert before the current function being generated
cgm.getModule().insert(mlir::Block::iterator(curCGF->CurFn), g);
} else {
// Insert at specified point or at end of module
if (insertPoint)
cgm.getModule().insert(insertPoint, g);
else
Expand Down Expand Up @@ -2675,6 +2683,11 @@ void CIRGenModule::setDSOLocal(mlir::Operation *op) const {
}
}

void CIRGenModule::setGVProperties(mlir::Operation *op, GlobalDecl gd) const {
assert(!cir::MissingFeatures::setDLLImportDLLExport());
setGVPropertiesAux(op, dyn_cast<NamedDecl>(gd.getDecl()));
}

void CIRGenModule::setGVProperties(mlir::Operation *op,
const NamedDecl *d) const {
assert(!cir::MissingFeatures::setDLLImportDLLExport());
Expand Down Expand Up @@ -2710,10 +2723,12 @@ cir::FuncOp CIRGenModule::createCIRFunction(mlir::Location loc, StringRef name,
// Some global emissions are triggered while emitting a function, e.g.
// void s() { x.method() }
//
// Be sure to insert a new function before a current one.
// Save the current function context for later insertion logic
auto *curCGF = getCurrCIRGenFun();
if (curCGF)
builder.setInsertionPoint(curCGF->CurFn);

// Clear insertion point to prevent auto-insertion by create()
// We'll manually insert at the correct location below
builder.clearInsertionPoint();

f = cir::FuncOp::create(builder, loc, name, ty);

Expand All @@ -2739,8 +2754,14 @@ cir::FuncOp CIRGenModule::createCIRFunction(mlir::Location loc, StringRef name,
// Set the special member attribute for this function, if applicable.
setCXXSpecialMemberAttr(f, fd);

if (!curCGF)
// Manually insert at the correct location
if (curCGF) {
// Insert before the current function being generated
theModule.insert(mlir::Block::iterator(curCGF->CurFn), f);
} else {
// Insert at end of module
theModule.push_back(f);
}
}
return f;
}
Expand Down Expand Up @@ -3064,20 +3085,27 @@ void CIRGenModule::setFunctionAttributes(GlobalDecl globalDecl,
// NOTE(cir): Original CodeGen checks if this is an intrinsic. In CIR we
// represent them in dedicated ops. The correct attributes are ensured during
// translation to LLVM. Thus, we don't need to check for them here.
assert(!isThunk && "isThunk NYI");

if (!isIncompleteFunction) {
const auto *funcDecl = dyn_cast<FunctionDecl>(globalDecl.getDecl());

if (!isIncompleteFunction)
setCIRFunctionAttributes(globalDecl,
getTypes().arrangeGlobalDeclaration(globalDecl),
func, isThunk);

// Add the Returned attribute for "this", except for iOS 5 and earlier
// where substantial code, including the libstdc++ dylib, was compiled with
// GCC and does not actually return "this".
if (!isThunk && getCXXABI().HasThisReturn(globalDecl) &&
!(getTriple().isiOS() && getTriple().isOSVersionLT(6))) {
llvm_unreachable("NYI");
}

// TODO(cir): Complete the remaining part of the function.
assert(!cir::MissingFeatures::setFunctionAttributes());

if (!isIncompleteFunction && func.isDeclaration())
getTargetCIRGenInfo().setTargetAttributes(globalDecl.getDecl(), func,
*this);
getTargetCIRGenInfo().setTargetAttributes(funcDecl, func, *this);

// TODO(cir): This needs a lot of work to better match CodeGen. That
// ultimately ends up in setGlobalVisibility, which already has the linkage of
Expand Down
9 changes: 5 additions & 4 deletions clang/lib/CIR/CodeGen/CIRGenModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -680,8 +680,9 @@ class CIRGenModule : public CIRGenTypeCache {
void setDSOLocal(mlir::Operation *Op) const;
/// Set visibility, dllimport/dllexport and dso_local.
/// This must be called after dllimport/dllexport is set.
void setGVProperties(mlir::Operation *Op, const NamedDecl *D) const;
void setGVPropertiesAux(mlir::Operation *Op, const NamedDecl *D) const;
void setGVProperties(mlir::Operation *op, GlobalDecl gd) const;
void setGVProperties(mlir::Operation *op, const NamedDecl *d) const;
void setGVPropertiesAux(mlir::Operation *op, const NamedDecl *d) const;

/// Set the TLS mode for the given global Op for the thread-local
/// variable declaration D.
Expand Down Expand Up @@ -760,8 +761,8 @@ class CIRGenModule : public CIRGenTypeCache {
void UpdateCompletedType(const clang::TagDecl *TD);

/// Set function attributes for a function declaration.
void setFunctionAttributes(GlobalDecl GD, cir::FuncOp F,
bool IsIncompleteFunction, bool IsThunk);
void setFunctionAttributes(GlobalDecl globalDecl, cir::FuncOp func,
bool isIncompleteFunction, bool isThunk);

/// Set the CIR function attributes (sext, zext, etc).
void setCIRFunctionAttributes(GlobalDecl GD, const CIRGenFunctionInfo &info,
Expand Down
Loading
Loading