aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CIR
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CIR')
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenCXXExpr.cpp37
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenClass.cpp25
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenFunction.cpp24
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenFunction.h2
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenModule.cpp6
5 files changed, 54 insertions, 40 deletions
diff --git a/clang/lib/CIR/CodeGen/CIRGenCXXExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenCXXExpr.cpp
index e0d30ad..8da832d 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCXXExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCXXExpr.cpp
@@ -85,13 +85,13 @@ RValue CIRGenFunction::emitCXXMemberOrOperatorMemberCallExpr(
return RValue::get(nullptr);
}
- bool trivialForCodegen =
- md->isTrivial() || (md->isDefaulted() && md->getParent()->isUnion());
- bool trivialAssignment =
- trivialForCodegen &&
- (md->isCopyAssignmentOperator() || md->isMoveAssignmentOperator()) &&
- !md->getParent()->mayInsertExtraPadding();
- (void)trivialAssignment;
+ // Note on trivial assignment
+ // --------------------------
+ // Classic codegen avoids generating the trivial copy/move assignment operator
+ // when it isn't necessary, choosing instead to just produce IR with an
+ // equivalent effect. We have chosen not to do that in CIR, instead emitting
+ // trivial copy/move assignment operators and allowing later transformations
+ // to optimize them away if appropriate.
// C++17 demands that we evaluate the RHS of a (possibly-compound) assignment
// operator before the LHS.
@@ -99,9 +99,10 @@ RValue CIRGenFunction::emitCXXMemberOrOperatorMemberCallExpr(
CallArgList *rtlArgs = nullptr;
if (auto *oce = dyn_cast<CXXOperatorCallExpr>(ce)) {
if (oce->isAssignmentOp()) {
- cgm.errorNYI(
- oce->getSourceRange(),
- "emitCXXMemberOrOperatorMemberCallExpr: assignment operator");
+ rtlArgs = &rtlArgStorage;
+ emitCallArgs(*rtlArgs, md->getType()->castAs<FunctionProtoType>(),
+ drop_begin(ce->arguments(), 1), ce->getDirectCallee(),
+ /*ParamsToSkip*/ 0);
}
}
@@ -121,19 +122,9 @@ RValue CIRGenFunction::emitCXXMemberOrOperatorMemberCallExpr(
return RValue::get(nullptr);
}
- if (trivialForCodegen) {
- if (isa<CXXDestructorDecl>(md))
- return RValue::get(nullptr);
-
- if (trivialAssignment) {
- cgm.errorNYI(ce->getSourceRange(),
- "emitCXXMemberOrOperatorMemberCallExpr: trivial assignment");
- return RValue::get(nullptr);
- }
-
- assert(md->getParent()->mayInsertExtraPadding() &&
- "unknown trivial member function");
- }
+ if ((md->isTrivial() || (md->isDefaulted() && md->getParent()->isUnion())) &&
+ isa<CXXDestructorDecl>(md))
+ return RValue::get(nullptr);
// Compute the function type we're calling
const CXXMethodDecl *calleeDecl = md;
diff --git a/clang/lib/CIR/CodeGen/CIRGenClass.cpp b/clang/lib/CIR/CodeGen/CIRGenClass.cpp
index 278cc893..da8166a 100644
--- a/clang/lib/CIR/CodeGen/CIRGenClass.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenClass.cpp
@@ -258,6 +258,31 @@ void CIRGenFunction::emitDelegateCXXConstructorCall(
/*Delegating=*/true, thisAddr, delegateArgs, loc);
}
+void CIRGenFunction::emitImplicitAssignmentOperatorBody(FunctionArgList &args) {
+ const auto *assignOp = cast<CXXMethodDecl>(curGD.getDecl());
+ assert(assignOp->isCopyAssignmentOperator() ||
+ assignOp->isMoveAssignmentOperator());
+ const Stmt *rootS = assignOp->getBody();
+ assert(isa<CompoundStmt>(rootS) &&
+ "Body of an implicit assignment operator should be compound stmt.");
+ const auto *rootCS = cast<CompoundStmt>(rootS);
+
+ assert(!cir::MissingFeatures::incrementProfileCounter());
+ assert(!cir::MissingFeatures::runCleanupsScope());
+
+ // Classic codegen uses a special class to attempt to replace member
+ // initializers with memcpy. We could possibly defer that to the
+ // lowering or optimization phases to keep the memory accesses more
+ // explicit. For now, we don't insert memcpy at all, though in some
+ // cases the AST contains a call to memcpy.
+ assert(!cir::MissingFeatures::assignMemcpyizer());
+ for (Stmt *s : rootCS->body())
+ if (emitStmt(s, /*useCurrentScope=*/true).failed())
+ cgm.errorNYI(s->getSourceRange(),
+ std::string("emitImplicitAssignmentOperatorBody: ") +
+ s->getStmtClassName());
+}
+
void CIRGenFunction::emitDelegatingCXXConstructorCall(
const CXXConstructorDecl *ctor, const FunctionArgList &args) {
assert(ctor->isDelegatingConstructor());
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
index c029853..c4efabd 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
@@ -462,21 +462,23 @@ cir::FuncOp CIRGenFunction::generateCode(clang::GlobalDecl gd, cir::FuncOp fn,
startFunction(gd, retTy, fn, funcType, args, loc, bodyRange.getBegin());
- if (isa<CXXDestructorDecl>(funcDecl))
+ if (isa<CXXDestructorDecl>(funcDecl)) {
getCIRGenModule().errorNYI(bodyRange, "C++ destructor definition");
- else if (isa<CXXConstructorDecl>(funcDecl))
+ } else if (isa<CXXConstructorDecl>(funcDecl)) {
emitConstructorBody(args);
- else if (getLangOpts().CUDA && !getLangOpts().CUDAIsDevice &&
- funcDecl->hasAttr<CUDAGlobalAttr>())
+ } else if (getLangOpts().CUDA && !getLangOpts().CUDAIsDevice &&
+ funcDecl->hasAttr<CUDAGlobalAttr>()) {
getCIRGenModule().errorNYI(bodyRange, "CUDA kernel");
- else if (isa<CXXMethodDecl>(funcDecl) &&
- cast<CXXMethodDecl>(funcDecl)->isLambdaStaticInvoker())
+ } else if (isa<CXXMethodDecl>(funcDecl) &&
+ cast<CXXMethodDecl>(funcDecl)->isLambdaStaticInvoker()) {
getCIRGenModule().errorNYI(bodyRange, "Lambda static invoker");
- else if (funcDecl->isDefaulted() && isa<CXXMethodDecl>(funcDecl) &&
- (cast<CXXMethodDecl>(funcDecl)->isCopyAssignmentOperator() ||
- cast<CXXMethodDecl>(funcDecl)->isMoveAssignmentOperator()))
- getCIRGenModule().errorNYI(bodyRange, "Default assignment operator");
- else if (body) {
+ } else if (funcDecl->isDefaulted() && isa<CXXMethodDecl>(funcDecl) &&
+ (cast<CXXMethodDecl>(funcDecl)->isCopyAssignmentOperator() ||
+ cast<CXXMethodDecl>(funcDecl)->isMoveAssignmentOperator())) {
+ // Implicit copy-assignment gets the same special treatment as implicit
+ // copy-constructors.
+ emitImplicitAssignmentOperatorBody(args);
+ } else if (body) {
if (mlir::failed(emitFunctionBody(body))) {
fn.erase();
return nullptr;
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index 759b83c..c2a7315 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -878,6 +878,8 @@ public:
mlir::LogicalResult emitFunctionBody(const clang::Stmt *body);
+ void emitImplicitAssignmentOperatorBody(FunctionArgList &args);
+
void emitInitializerForField(clang::FieldDecl *field, LValue lhs,
clang::Expr *init);
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index 0f38d9a..7198b23 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -393,12 +393,6 @@ void CIRGenModule::emitGlobal(clang::GlobalDecl gd) {
void CIRGenModule::emitGlobalFunctionDefinition(clang::GlobalDecl gd,
mlir::Operation *op) {
auto const *funcDecl = cast<FunctionDecl>(gd.getDecl());
- if (funcDecl->getIdentifier() == nullptr) {
- errorNYI(funcDecl->getSourceRange().getBegin(),
- "function definition with a non-identifier for a name");
- return;
- }
-
const CIRGenFunctionInfo &fi = getTypes().arrangeGlobalDeclaration(gd);
cir::FuncType funcType = getTypes().getFunctionType(fi);
cir::FuncOp funcOp = dyn_cast_if_present<cir::FuncOp>(op);