diff --git a/include/swift/AST/IRGenOptions.h b/include/swift/AST/IRGenOptions.h index 9b9db78a3b8..dc6cb89d402 100644 --- a/include/swift/AST/IRGenOptions.h +++ b/include/swift/AST/IRGenOptions.h @@ -146,6 +146,9 @@ public: /// objects. unsigned EmitStackPromotionChecks : 1; + /// Emit functions to separate sections. + unsigned FunctionSections : 1; + /// The maximum number of bytes used on a stack frame for stack promotion /// (includes alloc_stack allocations). unsigned StackPromotionSizeLimit = 1024; @@ -253,7 +256,7 @@ public: IntegratedREPL(false), DisableLLVMOptzns(false), DisableSwiftSpecificLLVMOptzns(false), DisableLLVMSLPVectorizer(false), DisableFPElim(true), Playground(false), EmitStackPromotionChecks(false), - PrintInlineTree(false), EmbedMode(IRGenEmbedMode::None), + FunctionSections(false), PrintInlineTree(false), EmbedMode(IRGenEmbedMode::None), HasValueNamesSetting(false), ValueNames(false), EnableReflectionMetadata(true), EnableReflectionNames(true), EnableAnonymousContextMangledNames(false), ForcePublicLinkage(false), diff --git a/include/swift/Option/FrontendOptions.td b/include/swift/Option/FrontendOptions.td index 7206520f310..2171a28eb0b 100644 --- a/include/swift/Option/FrontendOptions.td +++ b/include/swift/Option/FrontendOptions.td @@ -334,6 +334,10 @@ def disable_reflection_names : Flag<["-"], "disable-reflection-names">, HelpText<"Disable emission of names of stored properties and enum cases in" "reflection metadata">; +def function_sections: Flag<["-"], "function-sections">, + Flags<[FrontendOption, NoInteractiveOption]>, + HelpText<"Emit functions to separate sections.">; + def stack_promotion_checks : Flag<["-"], "emit-stack-promotion-checks">, HelpText<"Emit runtime checks for correct stack promotion of objects.">; diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 01a7e1d7c10..2fcb000f1d4 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -1136,6 +1136,8 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args, Opts.StackPromotionSizeLimit = limit; } + Opts.FunctionSections = Args.hasArg(OPT_function_sections); + if (Args.hasArg(OPT_autolink_force_load)) Opts.ForceLoadSymbolName = Args.getLastArgValue(OPT_module_link_name); diff --git a/lib/IRGen/IRGen.cpp b/lib/IRGen/IRGen.cpp index 4938a22b029..b8d10a5d860 100644 --- a/lib/IRGen/IRGen.cpp +++ b/lib/IRGen/IRGen.cpp @@ -162,6 +162,7 @@ swift::getIRTargetOptions(IRGenOptions &Opts, ASTContext &Ctx) { // Explicitly request debugger tuning for LLDB which is the default // on Darwin platforms but not on others. TargetOpts.DebuggerTuning = llvm::DebuggerKind::LLDB; + TargetOpts.FunctionSections = Opts.FunctionSections; auto *Clang = static_cast(Ctx.getClangModuleLoader()); clang::TargetOptions &ClangOpts = Clang->getTargetInfo().getTargetOpts(); diff --git a/test/LinkerSections/Inputs/FunctionSections.swift b/test/LinkerSections/Inputs/FunctionSections.swift new file mode 100644 index 00000000000..7ca4392d429 --- /dev/null +++ b/test/LinkerSections/Inputs/FunctionSections.swift @@ -0,0 +1,5 @@ +public typealias Void = () + +public func func1() -> Void {} + +public func func2() -> Void {} diff --git a/test/LinkerSections/Inputs/FunctionSectionsUse.swift b/test/LinkerSections/Inputs/FunctionSectionsUse.swift new file mode 100644 index 00000000000..af277d3cc86 --- /dev/null +++ b/test/LinkerSections/Inputs/FunctionSectionsUse.swift @@ -0,0 +1,3 @@ +import FunctionSections + +func1() diff --git a/test/LinkerSections/function_sections.swift b/test/LinkerSections/function_sections.swift new file mode 100644 index 00000000000..eb01d59563e --- /dev/null +++ b/test/LinkerSections/function_sections.swift @@ -0,0 +1,10 @@ +// REQUIRES: OS=linux-gnu || OS=linux-androideabi || OS=linux-android || OS=freebsd +// RUN: %empty-directory(%t) +// RUN: %target-build-swift -Xfrontend -function-sections -emit-module -emit-library -static -parse-stdlib %S/Inputs/FunctionSections.swift +// RUN: %target-build-swift -Xlinker --gc-sections -Xlinker -Map=%t/../../FunctionSections.map -I%t/../.. -L%t/../.. -lFunctionSections %S/Inputs/FunctionSectionsUse.swift +// RUN: %FileCheck %s < %t/../../FunctionSections.map + +// CHECK: Discarded input sections +// CHECK: .text.$s16FunctionSections5func2yyF +// CHECK: Memory map +// CHECK: .text.$s16FunctionSections5func1yyF diff --git a/test/LinkerSections/function_sections_ir_check.swift b/test/LinkerSections/function_sections_ir_check.swift new file mode 100644 index 00000000000..fd09e02ec3a --- /dev/null +++ b/test/LinkerSections/function_sections_ir_check.swift @@ -0,0 +1,12 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift -Xfrontend -function-sections -emit-library -emit-ir -static -parse-stdlib %S/Inputs/FunctionSections.swift | %FileCheck %s + +// CHECK: define {{(dllexport |protected )?}}swiftcc void @"$s16FunctionSections5func1yyF"() #0 { +// CHECK: entry: +// CHECK: ret void +// CHECK: } + +// CHECK: define {{(dllexport |protected )?}}swiftcc void @"$s16FunctionSections5func2yyF"() #0 { +// CHECK: entry: +// CHECK: ret void +// CHECK: }