Skip to content

[cxx-interop] Remove impl for constexpr members #60154

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jul 21, 2022
Merged
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
52 changes: 5 additions & 47 deletions lib/ClangImporter/ImportDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3209,49 +3209,8 @@ namespace {
return nullptr;
}

AccessorDecl *tryCreateConstexprAccessor(const clang::VarDecl *clangVar,
VarDecl *swiftVar) {
assert(clangVar->isConstexpr());
clangVar->evaluateValue();
auto evaluated = clangVar->getEvaluatedValue();
if (!evaluated)
return nullptr;

// If we have a constexpr var with an evaluated value, try to create an
// accessor for it. If we can remove all references to the global (which
// we should be able to do for constexprs) then we can remove the global
// entirely.
auto accessor = AccessorDecl::create(
Impl.SwiftContext, SourceLoc(), SourceLoc(), AccessorKind::Get,
swiftVar, SourceLoc(), StaticSpellingKind::KeywordStatic,
/*Async=*/false, /*AsyncLoc=*/SourceLoc(),
/*throws=*/false, SourceLoc(), /*genericParams*/ nullptr,
ParameterList::createEmpty(Impl.SwiftContext), swiftVar->getType(),
swiftVar->getDeclContext());
Expr *value = nullptr;
// TODO: add non-numeric types.
if (evaluated->isInt()) {
value = IntegerLiteralExpr::createFromUnsigned(
Impl.SwiftContext,
static_cast<unsigned>(
clangVar->getEvaluatedValue()->getInt().getZExtValue()));
} else if (evaluated->isFloat()) {
auto floatStr = evaluated->getAsString(Impl.getClangASTContext(),
clangVar->getType());
auto floatIdent = Impl.SwiftContext.getIdentifier(floatStr);
value = new (Impl.SwiftContext)
FloatLiteralExpr(floatIdent.str(), SourceLoc());
}
if (!value)
return nullptr;
auto returnStmt = new (Impl.SwiftContext) ReturnStmt(SourceLoc(), value);
auto body = BraceStmt::create(Impl.SwiftContext, SourceLoc(),
{returnStmt}, SourceLoc());
accessor->setBodyParsed(body);
return accessor;
}

Decl *VisitVarDecl(const clang::VarDecl *decl) {

// Variables are imported as... variables.
ImportedName importedName;
Optional<ImportedName> correctSwiftName;
Expand Down Expand Up @@ -3298,6 +3257,10 @@ namespace {
if (dc->isTypeContext())
isStatic = true;

// For now we don't import static constexpr
if (isStatic && decl->isConstexpr())
return nullptr;

auto introducer = Impl.shouldImportGlobalAsLet(decl->getType())
? VarDecl::Introducer::Let
: VarDecl::Introducer::Var;
Expand All @@ -3321,11 +3284,6 @@ namespace {
if (correctSwiftName)
markAsVariant(result, *correctSwiftName);

// For constexpr vars, we can create an accessor with a numeric literal.
if (decl->isConstexpr())
if (auto acc = tryCreateConstexprAccessor(decl, result))
result->setAccessors(SourceLoc(), {acc}, SourceLoc());

return result;
}

Expand Down
4 changes: 0 additions & 4 deletions test/Interop/Cxx/static/constexpr-static-member-var.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,4 @@ import StdlibUnittest

var ConstexprStaticMemberVarTestSuite = TestSuite("ConstexprStaticMemberVarTestSuite")

ConstexprStaticMemberVarTestSuite.test("constexpr-static-member") {
expectEqual(139, WithConstexprStaticMember.definedInline)
}

runAllTests()
54 changes: 1 addition & 53 deletions test/Interop/Cxx/static/static-member-var-irgen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,6 @@
// CHECK: @{{_ZN16WithStaticMember12staticMemberE|"\?staticMember@WithStaticMember@@2HA"}} = external {{(dso_local )?}}global i32, align 4
// CHECK: @{{_ZN26WithIncompleteStaticMember10selfMemberE|"\?selfMember@WithIncompleteStaticMember@@2V1@A"}} = {{external|linkonce_odr}} {{(dso_local )?}}global %class.WithIncompleteStaticMember, align 4

//TODO: This test uses only values of static const members, so it does not need
//to depend on external definitions. However, our code generation pattern loads
//the value dynamically. Instead, we should inline known constants. That would
//allow Swift code to even read the value of WithIncompleteStaticMember::notDefined.
// CHECK: @{{_ZN21WithConstStaticMember7definedE|"\?defined@WithConstStaticMember@@2HB"}} = {{available_externally|linkonce_odr}} {{(dso_local )?}}constant i32 48, {{(comdat, )?}}align 4
// CHECK: @{{_ZN21WithConstStaticMember16definedOutOfLineE|"\?definedOutOfLine@WithConstStaticMember@@2HB"}} = external {{(dso_local )?}}constant i32, align 4

// Make sure we remove constexpr globals after all uses have been inlined.
// CHECK-NOT: _ZN25WithConstexprStaticMember13definedInlineE
// CHECK-NOT: ?definedInline@WithConstexprStaticMember@@2HB
// CHECK-NOT: @_ZN25WithConstexprStaticMember20definedInlineWithArgE
// CHECK-NOT: @_ZN25WithConstexprStaticMember18definedInlineFloatE
// CHECK-NOT: @_ZN25WithConstexprStaticMember23definedInlineFromMethodE

import StaticMemberVar

public func readStaticMember() -> CInt {
Expand Down Expand Up @@ -54,55 +40,17 @@ public func writeSelfMember(_ m: WithIncompleteStaticMember) {
// public func readNotDefinedConstMember() -> CInt {
// return WithConstStaticMember.notDefined
// }

public func readDefinedConstMember() -> CInt {
return WithConstStaticMember.defined
}

// CHECK: define {{(protected |dllexport )?}}swiftcc i32 @"$s4main22readDefinedConstMembers5Int32VyF"() #0
// CHECK: [[VALUE:%.*]] = load i32, i32* getelementptr inbounds (%Ts5Int32V, %Ts5Int32V* bitcast (i32* @{{_ZN21WithConstStaticMember7definedE|"\?defined@WithConstStaticMember@@2HB"}} to %Ts5Int32V*), i32 0, i32 0), align 4
// CHECK: ret i32 [[VALUE]]

public func readDefinedOutOfLineConstMember() -> CInt {
return WithConstStaticMember.definedOutOfLine
}

// CHECK: define {{(protected |dllexport )?}}swiftcc i32 @"$s4main31readDefinedOutOfLineConstMembers5Int32VyF"() #0
// CHECK: [[VALUE:%.*]] = load i32, i32* getelementptr inbounds (%Ts5Int32V, %Ts5Int32V* bitcast (i32* @{{_ZN21WithConstStaticMember16definedOutOfLineE|"\?definedOutOfLine@WithConstStaticMember@@2HB"}} to %Ts5Int32V*), i32 0, i32 0), align 4
// CHECK: ret i32 [[VALUE]]

public func readConstexprStaticIntMembers() {
let x = WithConstexprStaticMember.definedInline
let y = WithConstexprStaticMember.definedInlineWithArg
}

// CHECK-LABEL: define {{(protected |dllexport )?}}swiftcc void @"$s4main29readConstexprStaticIntMembersyyF"()
// CHECK: call swiftcc i32 @"$sSo25WithConstexprStaticMemberV13definedInlines5Int32VvgZ"()
// CHECK: call swiftcc i32 @"$sSo25WithConstexprStaticMemberV013definedInlineA3Args5Int32VvgZ"()
// CHECK: ret void

// CHECK-LABEL: define linkonce_odr {{.*}}swiftcc i32 @"$sSo25WithConstexprStaticMemberV13definedInlines5Int32VvgZ"()
// CHECK-NEXT: entry
// CHECK-NEXT: ret i32 139

// CHECK-LABEL: define linkonce_odr {{.*}}swiftcc i32 @"$sSo25WithConstexprStaticMemberV013definedInlineA3Args5Int32VvgZ"()
// CHECK-NEXT: entry
// CHECK-NEXT: ret i32 42

public func readConstexprStaticFloatMembers() {
let x = WithConstexprStaticMember.definedInlineFloat
let y = WithConstexprStaticMember.definedInlineFromMethod
}

// CHECK-LABEL: define {{(protected |dllexport )?}}swiftcc void @"$s4main31readConstexprStaticFloatMembersyyF"()
// CHECK: call swiftcc float @"$sSo25WithConstexprStaticMemberV18definedInlineFloatSfvgZ"()
// CHECK: call swiftcc float @"$sSo25WithConstexprStaticMemberV23definedInlineFromMethodSfvgZ"()
// CHECK: ret void

// CHECK-LABEL: define linkonce_odr {{.*}}swiftcc float @"$sSo25WithConstexprStaticMemberV18definedInlineFloatSfvgZ"()
// CHECK-NEXT: entry
// CHECK-NEXT: ret float 1.390000e+02

// CHECK-LABEL: define linkonce_odr {{.*}}swiftcc float @"$sSo25WithConstexprStaticMemberV23definedInlineFromMethodSfvgZ"()
// CHECK-NEXT: entry
// CHECK-NEXT: ret float 4.200000e+01
// CHECK: ret i32 [[VALUE]]
28 changes: 1 addition & 27 deletions test/Interop/Cxx/static/static-member-var-silgen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,6 @@
// CHECK: sil_global public_external @{{_ZN16WithStaticMember12staticMemberE|\?staticMember@WithStaticMember@@2HA}} : $Int32
// CHECK: // clang name: WithIncompleteStaticMember::selfMember
// CHECK: sil_global public_external @{{_ZN26WithIncompleteStaticMember10selfMemberE|\?selfMember@WithIncompleteStaticMember@@2V1@A}} : $WithIncompleteStaticMember
// CHECK: // clang name: WithConstStaticMember::defined
// CHECK: sil_global public_external [let] @{{_ZN21WithConstStaticMember7definedE|\?defined@WithConstStaticMember@@2HB}} : $Int32
// CHECK: // clang name: WithConstStaticMember::definedOutOfLine
// CHECK: sil_global public_external [let] @{{_ZN21WithConstStaticMember16definedOutOfLineE|\?definedOutOfLine@WithConstStaticMember@@2HB}} : $Int32

import StaticMemberVar

func readStaticMember() -> CInt {
Expand Down Expand Up @@ -49,12 +44,10 @@ func writeSelfMember(_ m: WithIncompleteStaticMember) {
// CHECK: [[ADDR:%.*]] = global_addr @{{_ZN26WithIncompleteStaticMember10selfMemberE|\?selfMember@WithIncompleteStaticMember@@2V1@A}} : $*WithIncompleteStaticMember
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [dynamic] [[ADDR]] : $*WithIncompleteStaticMember
// CHECK: store %0 to [[ACCESS]] : $*WithIncompleteStaticMember

//TODO fix undefined reference to `WithConstStaticMember::notDefined`.
// func readNotDefinedConstMember() -> CInt {
// return WithConstStaticMember.notDefined
// }

func readDefinedConstMember() -> CInt {
return WithConstStaticMember.defined
}
Expand All @@ -63,25 +56,6 @@ func readDefinedConstMember() -> CInt {
// CHECK: [[ADDR:%.*]] = global_addr @{{_ZN21WithConstStaticMember7definedE|\?defined@WithConstStaticMember@@2HB}} : $*Int32
// CHECK: [[VALUE:%.*]] = load [[ADDR]] : $*Int32
// CHECK: return [[VALUE]] : $Int32

func readDefinedOutOfLineConstMember() -> CInt {
return WithConstStaticMember.definedOutOfLine
}

// CHECK: sil hidden @$s4main25readConstexprStaticMembers5Int32VyF : $@convention(thin) () -> Int32
// CHECK: [[META:%.*]] = metatype $@thin WithConstexprStaticMember.Type
// CHECK: [[ACC:%.*]] = function_ref @$sSo25WithConstexprStaticMemberV13definedInlines5Int32VvgZ : $@convention(method) (@thin WithConstexprStaticMember.Type) -> Int32
// CHECK: [[OUT:%.*]] = apply [[ACC]]([[META]]) : $@convention(method) (@thin WithConstexprStaticMember.Type) -> Int32
// CHECK: return [[OUT]] : $Int32
// CHECK-LABEL: end sil function '$s4main25readConstexprStaticMembers5Int32VyF'

// Make sure we also generate the accessor with a numeric literal.
// CHECK-LABEL: sil shared @$sSo25WithConstexprStaticMemberV13definedInlines5Int32VvgZ : $@convention(method) (@thin WithConstexprStaticMember.Type) -> Int32
// CHECK: [[IL:%.*]] = integer_literal $Builtin.Int32, 139
// CHECK: [[OUT:%.*]] = struct $Int32 ([[IL]] : $Builtin.Int32)
// CHECK: return [[OUT]] : $Int32
// CHECK-LABEL: end sil function '$sSo25WithConstexprStaticMemberV13definedInlines5Int32VvgZ'

func readConstexprStaticMember() -> CInt {
return WithConstexprStaticMember.definedInline
}
}
8 changes: 1 addition & 7 deletions test/Interop/Cxx/static/static-var-irgen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,9 @@ import StaticVar

public func initStaticVars() -> CInt {
return staticVar + staticVarInit + staticVarInlineInit + staticConst + staticConstInit
+ staticConstInlineInit + staticConstexpr + staticNonTrivial.val + staticConstNonTrivial.val
+ staticConstexprNonTrivial.val
+ staticConstInlineInit + staticNonTrivial.val + staticConstNonTrivial.val
}

// Constexpr vars should be inlined and removed.
// CHECK-NOT: ?staticConstexpr
// CHECK-NOT: _ZL15staticConstexpr

// CHECK: @{{_ZL9staticVar|staticVar}} = internal global i32 2, align 4
// CHECK: @{{_ZL13staticVarInit|staticVarInit}} = internal global i32 0, align 4
// CHECK: @{{_ZL19staticVarInlineInit|staticVarInlineInit}} = internal global i32 0, align 4
Expand All @@ -20,7 +15,6 @@ public func initStaticVars() -> CInt {
// CHECK: @{{_ZL21staticConstInlineInit|staticConstInlineInit}} = internal global i32 0, align 4
// CHECK: @{{_ZL16staticNonTrivial|staticNonTrivial}} = internal global %class.NonTrivial zeroinitializer, align 4
// CHECK: @{{_ZL21staticConstNonTrivial|staticConstNonTrivial}} = internal global %class.NonTrivial zeroinitializer, align 4
// CHECK: @{{_ZL25staticConstexprNonTrivial|staticConstexprNonTrivial}} = internal constant %class.NonTrivial { i32 8192 }, align 4

// CHECK: define internal void @{{__cxx_global_var_init|"\?\?__EstaticVarInit@@YAXXZ"}}()
// CHECK: %call = call i32 @{{_Z13makeStaticVarv|"\?makeStaticVar@@YAHXZ"}}()
Expand Down
8 changes: 1 addition & 7 deletions test/Interop/Cxx/static/static-var-silgen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,9 @@ import StaticVar

func initStaticVars() -> CInt {
return staticVar + staticVarInit + staticVarInlineInit + staticConst + staticConstInit
+ staticConstInlineInit + staticConstexpr + staticNonTrivial.val + staticConstNonTrivial.val
+ staticConstexprNonTrivial.val
+ staticConstInlineInit + staticNonTrivial.val + staticConstNonTrivial.val
}

// Constexpr globals should be inlined and removed.
// CHECK-NOT: sil_global public_external [let] @staticConstexpr : $Int32

// CHECK: // clang name: staticVar
// CHECK: sil_global public_external @staticVar : $Int32
// CHECK: // clang name: staticVarInit
Expand All @@ -27,8 +23,6 @@ func initStaticVars() -> CInt {
// CHECK: sil_global public_external @staticNonTrivial : $NonTrivial
// CHECK: // clang name: staticConstNonTrivial
// CHECK: sil_global public_external [let] @staticConstNonTrivial : $NonTrivial
// CHECK: // clang name: staticConstexprNonTrivial
// CHECK: sil_global public_external [let] @staticConstexprNonTrivial : $NonTrivial

func readStaticVar() -> CInt {
return staticVar
Expand Down
8 changes: 0 additions & 8 deletions test/Interop/Cxx/static/static-var.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,6 @@ StaticVarTestSuite.test("static-const-int-init") {
expectEqual(128, staticConstInit)
}

StaticVarTestSuite.test("static-constexpr-int") {
expectEqual(32, staticConstexpr)
}

StaticVarTestSuite.test("static-non-trivial") {
expectEqual(1024, staticNonTrivial.val)
}
Expand All @@ -75,8 +71,4 @@ StaticVarTestSuite.test("static-const-non-trivial") {
expectEqual(2048, staticConstNonTrivial.val)
}

StaticVarTestSuite.test("static-constexpr-non-trivial") {
expectEqual(8192, staticConstexprNonTrivial.val)
}

runAllTests()