Skip to content

Commit 57724cf

Browse files
andykaylorAnkur-0429
authored andcommitted
[CIR] Fix calling defined functions (llvm#137271)
Until now our function symbol lookup has been assuming that the function did not exist and creating a definition for it. This caused us to create a duplicate definition if we ever tried to call a function that was already defined. This change fixes that by adding handling for trying to look up existing global definitions before creating a new one.
1 parent 1f0dfff commit 57724cf

File tree

4 files changed

+59
-8
lines changed

4 files changed

+59
-8
lines changed

clang/include/clang/CIR/MissingFeatures.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ struct MissingFeatures {
160160
static bool lambdaFieldToName() { return false; }
161161
static bool targetSpecificCXXABI() { return false; }
162162
static bool moduleNameHash() { return false; }
163+
static bool setDSOLocal() { return false; }
163164

164165
// Missing types
165166
static bool dataMemberType() { return false; }

clang/lib/CIR/CodeGen/CIRGenModule.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -774,6 +774,58 @@ cir::FuncOp CIRGenModule::getOrCreateCIRFunction(
774774
StringRef mangledName, mlir::Type funcType, GlobalDecl gd, bool forVTable,
775775
bool dontDefer, bool isThunk, ForDefinition_t isForDefinition,
776776
mlir::ArrayAttr extraAttrs) {
777+
const Decl *d = gd.getDecl();
778+
779+
if (isThunk)
780+
errorNYI(d->getSourceRange(), "getOrCreateCIRFunction: thunk");
781+
782+
// In what follows, we continue past 'errorNYI' as if nothing happened because
783+
// the rest of the implementation is better than doing nothing.
784+
785+
if (const auto *fd = cast_or_null<FunctionDecl>(d)) {
786+
// For the device mark the function as one that should be emitted.
787+
if (getLangOpts().OpenMPIsTargetDevice && fd->isDefined() && !dontDefer &&
788+
!isForDefinition)
789+
errorNYI(fd->getSourceRange(),
790+
"getOrCreateCIRFunction: OpenMP target function");
791+
792+
// Any attempts to use a MultiVersion function should result in retrieving
793+
// the iFunc instead. Name mangling will handle the rest of the changes.
794+
if (fd->isMultiVersion())
795+
errorNYI(fd->getSourceRange(), "getOrCreateCIRFunction: multi-version");
796+
}
797+
798+
// Lookup the entry, lazily creating it if necessary.
799+
mlir::Operation *entry = getGlobalValue(mangledName);
800+
if (entry) {
801+
if (!isa<cir::FuncOp>(entry))
802+
errorNYI(d->getSourceRange(), "getOrCreateCIRFunction: non-FuncOp");
803+
804+
assert(!cir::MissingFeatures::weakRefReference());
805+
806+
// Handle dropped DLL attributes.
807+
if (d && !d->hasAttr<DLLImportAttr>() && !d->hasAttr<DLLExportAttr>()) {
808+
assert(!cir::MissingFeatures::setDLLStorageClass());
809+
assert(!cir::MissingFeatures::setDSOLocal());
810+
}
811+
812+
// If there are two attempts to define the same mangled name, issue an
813+
// error.
814+
auto fn = cast<cir::FuncOp>(entry);
815+
assert((!isForDefinition || !fn || !fn.isDeclaration()) &&
816+
"Duplicate function definition");
817+
if (fn && fn.getFunctionType() == funcType) {
818+
return fn;
819+
}
820+
821+
if (!isForDefinition) {
822+
return fn;
823+
}
824+
825+
// TODO(cir): classic codegen checks here if this is a llvm::GlobalAlias.
826+
// How will we support this?
827+
}
828+
777829
auto *funcDecl = llvm::cast_or_null<FunctionDecl>(gd.getDecl());
778830
bool invalidLoc = !funcDecl ||
779831
funcDecl->getSourceRange().getBegin().isInvalid() ||

clang/test/CIR/CodeGen/call.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
11
// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o - 2>&1 | FileCheck %s
22

3-
void f1();
3+
void f1() {}
44
void f2() {
55
f1();
66
}
77

88
// CHECK-LABEL: cir.func @_Z2f1v
9+
// CHECK-LABEL: cir.func @_Z2f2v
910
// CHECK: cir.call @_Z2f1v() : () -> ()
1011

11-
int f3();
12+
int f3() { return 2; }
1213
int f4() {
1314
int x = f3();
1415
return x;
1516
}
1617

18+
// CHECK-LABEL: cir.func @_Z2f3v() -> !s32i
1719
// CHECK-LABEL: cir.func @_Z2f4v() -> !s32i
18-
// CHECK: %[[#x:]] = cir.call @_Z2f3v() : () -> !s32i
19-
// CHECK-NEXT: cir.store %[[#x]], %{{.+}} : !s32i, !cir.ptr<!s32i>
20+
// CHECK: cir.call @_Z2f3v() : () -> !s32i

clang/test/CIR/CodeGen/namespace.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,7 @@
44
namespace {
55
int g1 = 1;
66

7-
// Note: This causes a warning about the function being undefined, but we
8-
// currently have a problem with duplicate definitions when we call functions.
9-
// This should be updated when that problem is fixed.
10-
void f1(void);
7+
void f1(void) {}
118
}
129

1310

0 commit comments

Comments
 (0)