Skip to content

Commit 9a06725

Browse files
authored
Merge pull request #1157 from swiftwasm/release/5.3
[pull] swiftwasm-release/5.3 from release/5.3
2 parents d44834e + edf8c20 commit 9a06725

File tree

11 files changed

+214
-25
lines changed

11 files changed

+214
-25
lines changed

include/swift/AST/IRGenOptions.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ class IRGenOptions {
194194
unsigned DisableLLVMSLPVectorizer : 1;
195195

196196
/// Disable frame pointer elimination?
197+
unsigned DisableFPElimLeaf : 1;
197198
unsigned DisableFPElim : 1;
198199

199200
/// Special codegen for playgrounds.
@@ -322,6 +323,7 @@ class IRGenOptions {
322323
DisableClangModuleSkeletonCUs(false), UseJIT(false),
323324
IntegratedREPL(false), DisableLLVMOptzns(false),
324325
DisableSwiftSpecificLLVMOptzns(false), DisableLLVMSLPVectorizer(false),
326+
DisableFPElimLeaf(false),
325327
DisableFPElim(true), Playground(false), EmitStackPromotionChecks(false),
326328
FunctionSections(false), PrintInlineTree(false), EmbedMode(IRGenEmbedMode::None),
327329
HasValueNamesSetting(false), ValueNames(false),

include/swift/Option/Options.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,6 +1012,10 @@ def enable_private_imports : Flag<["-"], "enable-private-imports">,
10121012
Flags<[FrontendOption, NoInteractiveOption, HelpHidden]>,
10131013
HelpText<"Allows this module's internal and private API to be accessed">;
10141014

1015+
def disable_leaf_frame_pointer_elim : Flag<["-"], "no-omit-leaf-frame-pointer">,
1016+
Flags<[FrontendOption, NoInteractiveOption, HelpHidden]>,
1017+
HelpText<"Don't omit the frame pointer for leaf functions">;
1018+
10151019
def sanitize_EQ : CommaJoined<["-"], "sanitize=">,
10161020
Flags<[FrontendOption, NoInteractiveOption]>, MetaVarName<"<check>">,
10171021
HelpText<"Turn on runtime checks for erroneous behavior.">;

lib/Driver/ToolChains.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,8 @@ void ToolChain::addCommonFrontendArgs(const OutputInfo &OI,
289289
arguments.push_back("-enable-anonymous-context-mangled-names");
290290
}
291291

292+
inputArgs.AddLastArg(arguments, options::OPT_disable_leaf_frame_pointer_elim);
293+
292294
// Pass through any subsystem flags.
293295
inputArgs.AddAllArgs(arguments, options::OPT_Xllvm);
294296
inputArgs.AddAllArgs(arguments, options::OPT_Xcc);

lib/Frontend/CompilerInvocation.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1464,6 +1464,9 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args,
14641464
getRuntimeCompatVersion();
14651465
}
14661466

1467+
if (Args.hasArg(OPT_disable_leaf_frame_pointer_elim))
1468+
Opts.DisableFPElimLeaf = true;
1469+
14671470
return false;
14681471
}
14691472

lib/IRGen/IRGenModule.cpp

Lines changed: 42 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -89,21 +89,34 @@ static llvm::PointerType *createStructPointerType(IRGenModule &IGM,
8989
return createStructType(IGM, name, types)->getPointerTo(DefaultAS);
9090
};
9191

92-
static clang::CodeGenerator *createClangCodeGenerator(ASTContext &Context,
93-
llvm::LLVMContext &LLVMContext,
94-
const IRGenOptions &Opts,
95-
StringRef ModuleName,
96-
StringRef PD) {
92+
static clang::CodeGenOptions::FramePointerKind
93+
shouldUseFramePointer(const IRGenOptions &Opts, const llvm::Triple &triple) {
94+
if (Opts.DisableFPElim) {
95+
// General frame pointer elimination is disabled.
96+
// Should we at least eliminate in leaf functions?
97+
// Currently we only do that on arm64 (this matches the behavior of clang).
98+
return Opts.DisableFPElimLeaf
99+
? clang::CodeGenOptions::FramePointerKind::All
100+
: triple.isAArch64()
101+
? clang::CodeGenOptions::FramePointerKind::NonLeaf
102+
: clang::CodeGenOptions::FramePointerKind::All;
103+
}
104+
105+
return clang::CodeGenOptions::FramePointerKind::None;
106+
}
107+
108+
static clang::CodeGenerator *
109+
createClangCodeGenerator(ASTContext &Context, llvm::LLVMContext &LLVMContext,
110+
const IRGenOptions &Opts, StringRef ModuleName,
111+
StringRef PD, const llvm::Triple &triple) {
97112
auto Loader = Context.getClangModuleLoader();
98113
auto *Importer = static_cast<ClangImporter*>(&*Loader);
99114
assert(Importer && "No clang module loader!");
100115
auto &ClangContext = Importer->getClangASTContext();
101116

102117
auto &CGO = Importer->getClangCodeGenOpts();
103118
CGO.OptimizationLevel = Opts.shouldOptimize() ? 3 : 0;
104-
CGO.setFramePointer(Opts.DisableFPElim
105-
? clang::CodeGenOptions::FramePointerKind::All
106-
: clang::CodeGenOptions::FramePointerKind::None);
119+
CGO.setFramePointer(shouldUseFramePointer(Opts, triple));
107120
CGO.DiscardValueNames = !Opts.shouldProvideValueNames();
108121
switch (Opts.DebugInfoLevel) {
109122
case IRGenDebugInfoLevel::None:
@@ -193,17 +206,17 @@ static void sanityCheckStdlib(IRGenModule &IGM) {
193206

194207
IRGenModule::IRGenModule(IRGenerator &irgen,
195208
std::unique_ptr<llvm::TargetMachine> &&target,
196-
SourceFile *SF,
197-
StringRef ModuleName, StringRef OutputFilename,
209+
SourceFile *SF, StringRef ModuleName,
210+
StringRef OutputFilename,
198211
StringRef MainInputFilenameForDebugInfo,
199212
StringRef PrivateDiscriminator)
200-
: LLVMContext(new llvm::LLVMContext()),
201-
IRGen(irgen), Context(irgen.SIL.getASTContext()),
213+
: LLVMContext(new llvm::LLVMContext()), IRGen(irgen),
214+
Context(irgen.SIL.getASTContext()),
202215
// The LLVMContext (and the IGM itself) will get deleted by the IGMDeleter
203216
// as long as the IGM is registered with the IRGenerator.
204-
ClangCodeGen(createClangCodeGenerator(Context, *LLVMContext,
205-
irgen.Opts,
206-
ModuleName, PrivateDiscriminator)),
217+
ClangCodeGen(createClangCodeGenerator(Context, *LLVMContext, irgen.Opts,
218+
ModuleName, PrivateDiscriminator,
219+
irgen.getEffectiveClangTriple())),
207220
Module(*ClangCodeGen->GetModule()),
208221
DataLayout(irgen.getClangDataLayout()),
209222
Triple(irgen.getEffectiveClangTriple()), TargetMachine(std::move(target)),
@@ -1004,7 +1017,20 @@ bool swift::irgen::shouldRemoveTargetFeature(StringRef feature) {
10041017

10051018
void IRGenModule::setHasFramePointer(llvm::AttrBuilder &Attrs,
10061019
bool HasFramePointer) {
1007-
Attrs.addAttribute("frame-pointer", HasFramePointer ? "all" : "none");
1020+
if (!HasFramePointer) {
1021+
Attrs.addAttribute("frame-pointer", "none");
1022+
return;
1023+
}
1024+
if (IRGen.Opts.DisableFPElimLeaf) {
1025+
Attrs.addAttribute("frame-pointer", "all");
1026+
return;
1027+
}
1028+
1029+
// We omit frame pointers for leaf functions only for arm64 for now (matching
1030+
// clang's behavior).
1031+
auto framePointer =
1032+
IRGen.getEffectiveClangTriple().isAArch64() ? "non-leaf" : "all";
1033+
Attrs.addAttribute("frame-pointer", framePointer);
10081034
}
10091035

10101036
void IRGenModule::setHasFramePointer(llvm::Function *F,

lib/Sema/ConstraintSystem.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2062,7 +2062,7 @@ void ConstraintSystem::bindOverloadType(
20622062

20632063
// If this is used inside of the keypath expression, we need to make
20642064
// sure that argument is Hashable.
2065-
if (isa<KeyPathExpr>(locator->getAnchor()))
2065+
if (llvm::isa_and_nonnull<KeyPathExpr>(locator->getAnchor()))
20662066
verifyThatArgumentIsHashable(0, argType, locator);
20672067

20682068
// The resolved decl is for subscript(dynamicMember:), however the original
@@ -2184,7 +2184,7 @@ void ConstraintSystem::bindOverloadType(
21842184
addConstraint(ConstraintKind::Equal, memberTy, leafTy, keyPathLoc);
21852185
}
21862186

2187-
if (isa<KeyPathExpr>(locator->getAnchor()))
2187+
if (llvm::isa_and_nonnull<KeyPathExpr>(locator->getAnchor()))
21882188
verifyThatArgumentIsHashable(0, keyPathTy, locator);
21892189

21902190
// The resolved decl is for subscript(dynamicMember:), however the

test/IRGen/c_globals.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,4 @@ public func testCaptureGlobal() {
3232
}
3333

3434
// CHECK-DAG: attributes [[CLANG_FUNC_ATTR]] = { noinline nounwind {{.*}}"frame-pointer"="all"{{.*}}
35-
// CHECK-DAG: attributes [[SWIFT_FUNC_ATTR]] = { "frame-pointer"="all" {{.*}}"target-cpu"
35+
// CHECK-DAG: attributes [[SWIFT_FUNC_ATTR]] = { {{.*}}"frame-pointer"="all" {{.*}}"target-cpu"

test/IRGen/framepointer.sil

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// RUN: %target-swift-frontend -primary-file %s -emit-ir | %FileCheck %s --check-prefix=CHECK
2+
// RUN: %target-swift-frontend -primary-file %s -emit-ir -no-omit-leaf-frame-pointer| %FileCheck %s --check-prefix=CHECK-ALL
3+
// RUN: %target-swift-frontend -primary-file %s -S | %FileCheck %s --check-prefix=CHECKASM --check-prefix=CHECKASM-%target-os-%target-cpu
4+
5+
// REQUIRES: CPU=x86_64
6+
7+
sil_stage canonical
8+
9+
import Swift
10+
11+
sil @leaf_function_no_frame_pointer : $@convention(thin) (Int32) -> Int32 {
12+
entry(%i : $Int32):
13+
return %i : $Int32
14+
}
15+
16+
sil @non_leaf_function_with_frame_pointer : $@convention(thin) (Int32) -> Int32 {
17+
entry(%i : $Int32):
18+
%f = function_ref @leaf_function_no_frame_pointer : $@convention(thin) (Int32) -> Int32
19+
%r = apply %f(%i) : $@convention(thin) (Int32) -> Int32
20+
return %r : $Int32
21+
}
22+
23+
// CHECK: define{{.*}} swiftcc i32 @leaf_function_no_frame_pointer(i32 %0) [[ATTR:#.*]] {
24+
// CHECK: entry:
25+
// CHECK: ret i32 %0
26+
// CHECK: }
27+
28+
// CHECK: define{{.*}} swiftcc i32 @non_leaf_function_with_frame_pointer(i32 %0) [[ATTR]] {
29+
// CHECK: entry:
30+
// CHECK: %1 = call swiftcc i32 @leaf_function_no_frame_pointer(i32 %0)
31+
// CHECK: ret i32 %1
32+
// CHECK: }
33+
34+
// CHECK: attributes [[ATTR]] = {{{.*}}"frame-pointer"="all"
35+
36+
// CHECK-ALL: define{{.*}} swiftcc i32 @leaf_function_no_frame_pointer(i32 %0) [[ATTR:#.*]] {
37+
// CHECK-ALL: entry:
38+
// CHECK-ALL: ret i32 %0
39+
// CHECK-ALL: }
40+
41+
// CHECK-ALL: define{{.*}} swiftcc i32 @non_leaf_function_with_frame_pointer(i32 %0) [[ATTR]] {
42+
// CHECK-ALL: entry:
43+
// CHECK-ALL: %1 = call swiftcc i32 @leaf_function_no_frame_pointer(i32 %0)
44+
// CHECK-ALL: ret i32 %1
45+
// CHECK-ALL: }
46+
47+
// CHECK-ALL: attributes [[ATTR]] = {{{.*}}"frame-pointer"="all"
48+
49+
// Silence other os-archs.
50+
// CHECKASM: {{.*}}
51+
52+
// CHECKASM-macosx-x86_64-LABEL: _leaf_function_no_frame_pointer:
53+
// CHECKASM-macosx-x86_64: push
54+
// CHECKASM-macosx-x86_64: movl %edi, %eax
55+
// CHECKASM-macosx-x86_64: pop
56+
// CHECKASM-macosx-x86_64: ret
57+
58+
59+
// CHECKASM-macosx-x86_64-LABEL: _non_leaf_function_with_frame_pointer:
60+
// CHECKASM-macosx-x86_64: pushq %rbp
61+
// CHECKASM-macosx-x86_64: movq %rsp, %rbp
62+
// CHECKASM-macosx-x86_64: callq _leaf_function_no_frame_pointer
63+
// CHECKASM-macosx-x86_64: popq %rbp
64+
// CHECKASM-macosx-x86_64: ret

test/IRGen/framepointer_arm64.sil

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// RUN: %target-swift-frontend -target arm64-apple-ios8.0 -primary-file %s -emit-ir | %FileCheck %s --check-prefix=CHECK
2+
// RUN: %target-swift-frontend -target arm64-apple-ios8.0 -primary-file %s -emit-ir -no-omit-leaf-frame-pointer| %FileCheck %s --check-prefix=CHECK-ALL
3+
// RUN: %target-swift-frontend -target arm64-apple-ios8.0 -primary-file %s -S | %FileCheck %s --check-prefix=CHECKASM
4+
// RUN: %target-swift-frontend -target arm64-apple-ios8.0 -primary-file %s -S -no-omit-leaf-frame-pointer | %FileCheck %s --check-prefix=CHECKASM-ALL
5+
6+
// REQUIRES: CODEGENERATOR=AArch64
7+
8+
// UNSUPPORTED: OS=linux-gnu
9+
// UNSUPPORTED: OS=windows
10+
11+
sil_stage canonical
12+
13+
import Swift
14+
15+
sil @leaf_function_no_frame_pointer : $@convention(thin) (Int32) -> Int32 {
16+
entry(%i : $Int32):
17+
return %i : $Int32
18+
}
19+
20+
sil @non_leaf_function_with_frame_pointer : $@convention(thin) (Int32) -> Int32 {
21+
entry(%i : $Int32):
22+
%f = function_ref @leaf_function_no_frame_pointer : $@convention(thin) (Int32) -> Int32
23+
%r = apply %f(%i) : $@convention(thin) (Int32) -> Int32
24+
return %r : $Int32
25+
}
26+
27+
// CHECK: define{{.*}} swiftcc i32 @leaf_function_no_frame_pointer(i32 %0) [[ATTR:#.*]] {
28+
// CHECK: entry:
29+
// CHECK: ret i32 %0
30+
// CHECK: }
31+
32+
// CHECK: define{{.*}} swiftcc i32 @non_leaf_function_with_frame_pointer(i32 %0) [[ATTR]] {
33+
// CHECK: entry:
34+
// CHECK: %1 = call swiftcc i32 @leaf_function_no_frame_pointer(i32 %0)
35+
// CHECK: ret i32 %1
36+
// CHECK: }
37+
38+
// CHECK: attributes [[ATTR]] = {{{.*}}"frame-pointer"="non-leaf"
39+
40+
// CHECK-ALL: define{{.*}} swiftcc i32 @leaf_function_no_frame_pointer(i32 %0) [[ATTR:#.*]] {
41+
// CHECK-ALL: entry:
42+
// CHECK-ALL: ret i32 %0
43+
// CHECK-ALL: }
44+
45+
// CHECK-ALL: define{{.*}} swiftcc i32 @non_leaf_function_with_frame_pointer(i32 %0) [[ATTR]] {
46+
// CHECK-ALL: entry:
47+
// CHECK-ALL: %1 = call swiftcc i32 @leaf_function_no_frame_pointer(i32 %0)
48+
// CHECK-ALL: ret i32 %1
49+
// CHECK-ALL: }
50+
51+
// CHECK-ALL: attributes [[ATTR]] = {{{.*}}"frame-pointer"="all"
52+
53+
// CHECKASM-LABEL: _leaf_function_no_frame_pointer:
54+
// CHECKASM-NOT: stp
55+
// CHECKASM-NOT: ldp
56+
// CHECKASM: ret
57+
58+
// CHECKASM-LABEL: _non_leaf_function_with_frame_pointer:
59+
// CHECKASM: stp
60+
// CHECKASM: _leaf_function_no_frame_pointer
61+
// CHECKASM: ldp
62+
// CHECKASM: ret
63+
64+
// CHECKASM-ALL-LABEL: _leaf_function_no_frame_pointer:
65+
// CHECKASM-ALL: stp
66+
// CHECKASM-ALL: ldp
67+
// CHECKASM-ALL: ret
68+
69+
// CHECKASM-ALL-LABEL: _non_leaf_function_with_frame_pointer:
70+
// CHECKASM-ALL: stp
71+
// CHECKASM-ALL: _leaf_function_no_frame_pointer
72+
// CHECKASM-ALL: ldp
73+
// CHECKASM-ALL: ret

test/Index/index_keypath_member_lookup.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,3 +137,24 @@ func testExplicit(r: Lens<Rectangle>, a: Lens<[Int]>) {
137137
// CHECK: [[EA_LINE]]:8 | instance-property/subscript/Swift | subscript(dynamicMember:) | [[SUB_USR]] | Ref,Read,RelCont | rel: 1
138138
// CHECK: [[EA_LINE]]:26 | instance-property/subscript/Swift | subscript(_:) | s:SayxSicip | Ref,Read,RelCont | rel: 1
139139
}
140+
141+
// Don't crash: rdar63558609
142+
//
143+
@dynamicMemberLookup
144+
protocol Foo {
145+
var prop: Bar {get}
146+
// CHECK: [[@LINE-1]]:7 | instance-property/Swift | prop | [[PROP_USR:.*]] | Def,RelChild | rel: 1
147+
}
148+
struct Bar {
149+
let enabled = false
150+
}
151+
extension Foo {
152+
subscript<T>(dynamicMember keyPath: KeyPath<Bar,T>) -> T {
153+
// CHECK: [[@LINE-1]]:3 | instance-property/subscript/Swift | subscript(dynamicMember:) | [[SUB2_USR:.*]] | Def,RelChild | rel: 1
154+
// CHECK: [[@LINE-2]]:60 | instance-method/acc-get/Swift | getter:subscript(dynamicMember:) | {{.*}} | Def,Dyn,RelChild,RelAcc | rel: 1
155+
// CHECK-NEXT: RelChild,RelAcc | instance-property/subscript/Swift | subscript(dynamicMember:) | [[SUB2_USR]]
156+
157+
prop[keyPath: keyPath]
158+
// CHECK: [[@LINE-1]]:5 | instance-property/Swift | prop | [[PROP_USR]] | Ref,Read,RelCont | rel: 1
159+
}
160+
}

0 commit comments

Comments
 (0)