-
Notifications
You must be signed in to change notification settings - Fork 14.3k
CodeGen: support static linking for libclosure #125384
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
Conversation
@llvm/pr-subscribers-clang-codegen @llvm/pr-subscribers-clang-driver Author: Saleem Abdulrasool (compnerd) ChangesWhen building on Windows, dealing with the BlocksRuntime is slightly more complicated. As we are not guaranteed a formward declaration for the blocks runtime ABI symbols, we may generate the declarations for them. In order to properly link against the well-known types, we always annotated them as Introduce a new driver/cc1 option Full diff: https://github.com/llvm/llvm-project/pull/125384.diff 6 Files Affected:
diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def
index 386652d2efa9e1..9ca1fe6566d6ad 100644
--- a/clang/include/clang/Basic/CodeGenOptions.def
+++ b/clang/include/clang/Basic/CodeGenOptions.def
@@ -469,6 +469,10 @@ CODEGENOPT(CtorDtorReturnThis, 1, 0)
/// by the Windows kernel to enable import call optimization.
CODEGENOPT(ImportCallOptimization, 1, 0)
+/// Controls whether we generate code for static linking of libclosure
+/// (BlocksRuntime) on Windows.
+CODEGENOPT(StaticClosure, 1, 0)
+
/// FIXME: Make DebugOptions its own top-level .def file.
#include "DebugOptions.def"
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 0ab923fcdd5838..7f2b8b74bce79c 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -5825,6 +5825,8 @@ def start_no_unused_arguments : Flag<["--"], "start-no-unused-arguments">,
HelpText<"Don't emit warnings about unused arguments for the following arguments">;
def static_libgcc : Flag<["-"], "static-libgcc">;
def static_libstdcxx : Flag<["-"], "static-libstdc++">;
+def static_libclosure : Flag<["-"], "static-libclosure">,
+ Visibility<[ClangOption, CC1Option]>;
def static : Flag<["-", "--"], "static">, Group<Link_Group>,
Visibility<[ClangOption, FlangOption]>,
Flags<[NoArgumentUnused]>;
diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp
index a7584a95c8ca7b..aaba354c08547d 100644
--- a/clang/lib/CodeGen/CGBlocks.cpp
+++ b/clang/lib/CodeGen/CGBlocks.cpp
@@ -2800,7 +2800,8 @@ static void configureBlocksRuntimeObject(CodeGenModule &CGM,
llvm::Constant *C) {
auto *GV = cast<llvm::GlobalValue>(C->stripPointerCasts());
- if (CGM.getTarget().getTriple().isOSBinFormatCOFF()) {
+ if (!CGM.getCodeGenOpts().StaticClosure &&
+ CGM.getTarget().getTriple().isOSBinFormatCOFF()) {
const IdentifierInfo &II = CGM.getContext().Idents.get(C->getName());
TranslationUnitDecl *TUDecl = CGM.getContext().getTranslationUnitDecl();
DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl);
@@ -2815,7 +2816,6 @@ static void configureBlocksRuntimeObject(CodeGenModule &CGM,
(ND = dyn_cast<VarDecl>(Result)))
break;
- // TODO: support static blocks runtime
if (GV->isDeclaration() && (!ND || !ND->hasAttr<DLLExportAttr>())) {
GV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
GV->setLinkage(llvm::GlobalValue::ExternalLinkage);
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 9b5132c5625faa..ad73ac4dd8f73d 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -5580,6 +5580,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_static))
CmdArgs.push_back("-static-define");
+ Args.AddLastArg(CmdArgs, options::OPT_static_libclosure);
+
if (Args.hasArg(options::OPT_municode))
CmdArgs.push_back("-DUNICODE");
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 11fd6ab7f52a79..de31c3c40fecf0 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -1843,6 +1843,9 @@ void CompilerInvocationBase::GenerateCodeGenArgs(const CodeGenOptions &Opts,
GenerateArg(Consumer, OPT_fno_finite_loops);
break;
}
+
+ if (Opts.StaticClosure)
+ GenerateArg(Consumer, OPT_static_libclosure);
}
bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,
@@ -2330,6 +2333,8 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,
if (!Opts.EmitIEEENaNCompliantInsts && !LangOptsRef.NoHonorNaNs)
Diags.Report(diag::err_drv_amdgpu_ieee_without_no_honor_nans);
+ Opts.StaticClosure = Args.hasArg(options::OPT_static_libclosure);
+
return Diags.getNumErrors() == NumErrorsBefore;
}
diff --git a/clang/test/CodeGen/blocks-windows.c b/clang/test/CodeGen/blocks-windows.c
index 3da5f3d99bd23d..7c6b5cc85fdff4 100644
--- a/clang/test/CodeGen/blocks-windows.c
+++ b/clang/test/CodeGen/blocks-windows.c
@@ -1,6 +1,7 @@
// RUN: %clang_cc1 -triple thumbv7-windows -fblocks -fdeclspec -DBLOCKS_IN_BLOCKS_DECL -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-BLOCKS-IN-BLOCKS-DECL
// RUN: %clang_cc1 -triple thumbv7-windows -fblocks -fdeclspec -DBLOCKS_IN_BLOCKS_DEFN -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-BLOCKS-IN-BLOCKS-DEFN
// RUN: %clang_cc1 -triple thumbv7-windows -fblocks -fdeclspec -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-BLOCKS-NOT-IN-BLOCKS
+// RUN: %clang_cc1 -triple thumbv7-windows -fblocks -fdeclspec -static-libclosure -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-BLOCKS-NOT-IN-STATIC-BLOCKS
// RUN: %clang_cc1 -triple thumbv7-windows -fblocks -fdeclspec -DBLOCKS_NOT_IN_BLOCKS_EXTERN -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-BLOCKS-NOT-IN-BLOCKS-EXTERN
// RUN: %clang_cc1 -triple thumbv7-windows -fblocks -fdeclspec -DBLOCKS_NOT_IN_BLOCKS_EXTERN_DLLIMPORT -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-BLOCKS-NOT-IN-BLOCKS-EXTERN-DLLIMPORT
// RUN: %clang_cc1 -triple thumbv7-windows -fblocks -fdeclspec -DBLOCKS_NOT_IN_BLOCKS_DLLIMPORT -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-BLOCKS-NOT-IN-BLOCKS-DLLIMPORT
@@ -8,6 +9,7 @@
// RUN: %clang_cc1 -triple thumbv7-windows -fblocks -fdeclspec -DBLOCKS_IN_BLOCKS_DECL -Os -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-BLOCKS-IN-BLOCKS-DECL
// RUN: %clang_cc1 -triple thumbv7-windows -fblocks -fdeclspec -DBLOCKS_IN_BLOCKS_DEFN -Os -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-BLOCKS-IN-BLOCKS-DEFN
// RUN: %clang_cc1 -triple thumbv7-windows -fblocks -fdeclspec -Os -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-BLOCKS-NOT-IN-BLOCKS
+// RUN: %clang_cc1 -triple thumbv7-windows -fblocks -fdeclspec -Os -static-libclosure -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-BLOCKS-NOT-IN-STATIC-BLOCKS
// RUN: %clang_cc1 -triple thumbv7-windows -fblocks -fdeclspec -DBLOCKS_NOT_IN_BLOCKS_EXTERN -Os -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-BLOCKS-NOT-IN-BLOCKS-EXTERN
// RUN: %clang_cc1 -triple thumbv7-windows -fblocks -fdeclspec -DBLOCKS_NOT_IN_BLOCKS_EXTERN_DLLIMPORT -Os -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-BLOCKS-NOT-IN-BLOCKS-EXTERN-DLLIMPORT
// RUN: %clang_cc1 -triple thumbv7-windows -fblocks -fdeclspec -DBLOCKS_NOT_IN_BLOCKS_DLLIMPORT -Os -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-BLOCKS-NOT-IN-BLOCKS-DLLIMPORT
@@ -15,6 +17,7 @@
// RUN: %clang_cc1 -triple i686-windows -fblocks -fdeclspec -DBLOCKS_IN_BLOCKS_DECL -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-BLOCKS-IN-BLOCKS-DECL
// RUN: %clang_cc1 -triple i686-windows -fblocks -fdeclspec -DBLOCKS_IN_BLOCKS_DEFN -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-BLOCKS-IN-BLOCKS-DEFN
// RUN: %clang_cc1 -triple i686-windows -fblocks -fdeclspec -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-BLOCKS-NOT-IN-BLOCKS
+// RUN: %clang_cc1 -triple i686-windows -fblocks -fdeclspec -static-libclosure -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-BLOCKS-NOT-IN-STATIC-BLOCKS
// RUN: %clang_cc1 -triple i686-windows -fblocks -fdeclspec -DBLOCKS_NOT_IN_BLOCKS_EXTERN -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-BLOCKS-NOT-IN-BLOCKS-EXTERN
// RUN: %clang_cc1 -triple i686-windows -fblocks -fdeclspec -DBLOCKS_NOT_IN_BLOCKS_EXTERN_DLLIMPORT -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-BLOCKS-NOT-IN-BLOCKS-EXTERN-DLLIMPORT
// RUN: %clang_cc1 -triple i686-windows -fblocks -fdeclspec -DBLOCKS_NOT_IN_BLOCKS_DLLIMPORT -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-BLOCKS-NOT-IN-BLOCKS-DLLIMPORT
@@ -22,6 +25,7 @@
// RUN: %clang_cc1 -triple i686-windows -fblocks -fdeclspec -DBLOCKS_IN_BLOCKS_DECL -Os -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-BLOCKS-IN-BLOCKS-DECL
// RUN: %clang_cc1 -triple i686-windows -fblocks -fdeclspec -DBLOCKS_IN_BLOCKS_DEFN -Os -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-BLOCKS-IN-BLOCKS-DEFN
// RUN: %clang_cc1 -triple i686-windows -fblocks -fdeclspec -Os -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-BLOCKS-NOT-IN-BLOCKS
+// RUN: %clang_cc1 -triple i686-windows -fblocks -fdeclspec -Os -static-libclosure -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-BLOCKS-NOT-IN-STATIC-BLOCKS
// RUN: %clang_cc1 -triple i686-windows -fblocks -fdeclspec -DBLOCKS_NOT_IN_BLOCKS_EXTERN -Os -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-BLOCKS-NOT-IN-BLOCKS-EXTERN
// RUN: %clang_cc1 -triple i686-windows -fblocks -fdeclspec -DBLOCKS_NOT_IN_BLOCKS_EXTERN_DLLIMPORT -Os -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-BLOCKS-NOT-IN-BLOCKS-EXTERN-DLLIMPORT
// RUN: %clang_cc1 -triple i686-windows -fblocks -fdeclspec -DBLOCKS_NOT_IN_BLOCKS_DLLIMPORT -Os -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-BLOCKS-NOT-IN-BLOCKS-DLLIMPORT
@@ -29,6 +33,7 @@
// RUN: %clang_cc1 -triple x86_64-windows -fblocks -fdeclspec -DBLOCKS_IN_BLOCKS_DECL -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-BLOCKS-IN-BLOCKS-DECL
// RUN: %clang_cc1 -triple x86_64-windows -fblocks -fdeclspec -DBLOCKS_IN_BLOCKS_DEFN -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-BLOCKS-IN-BLOCKS-DEFN
// RUN: %clang_cc1 -triple x86_64-windows -fblocks -fdeclspec -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-BLOCKS-NOT-IN-BLOCKS
+// RUN: %clang_cc1 -triple x86_64-windows -fblocks -fdeclspec -static-libclosure -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-BLOCKS-NOT-IN-STATIC-BLOCKS
// RUN: %clang_cc1 -triple x86_64-windows -fblocks -fdeclspec -DBLOCKS_NOT_IN_BLOCKS_EXTERN -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-BLOCKS-NOT-IN-BLOCKS-EXTERN
// RUN: %clang_cc1 -triple x86_64-windows -fblocks -fdeclspec -DBLOCKS_NOT_IN_BLOCKS_EXTERN_DLLIMPORT -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-BLOCKS-NOT-IN-BLOCKS-EXTERN-DLLIMPORT
// RUN: %clang_cc1 -triple x86_64-windows -fblocks -fdeclspec -DBLOCKS_NOT_IN_BLOCKS_DLLIMPORT -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-BLOCKS-NOT-IN-BLOCKS-DLLIMPORT
@@ -36,6 +41,7 @@
// RUN: %clang_cc1 -triple x86_64-windows -fblocks -fdeclspec -DBLOCKS_IN_BLOCKS_DECL -Os -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-BLOCKS-IN-BLOCKS-DECL
// RUN: %clang_cc1 -triple x86_64-windows -fblocks -fdeclspec -DBLOCKS_IN_BLOCKS_DEFN -Os -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-BLOCKS-IN-BLOCKS-DEFN
// RUN: %clang_cc1 -triple x86_64-windows -fblocks -fdeclspec -Os -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-BLOCKS-NOT-IN-BLOCKS
+// RUN: %clang_cc1 -triple x86_64-windows -fblocks -fdeclspec -Os -static-libclosure -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-BLOCKS-NOT-IN-STATIC-BLOCKS
// RUN: %clang_cc1 -triple x86_64-windows -fblocks -fdeclspec -DBLOCKS_NOT_IN_BLOCKS_EXTERN -Os -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-BLOCKS-NOT-IN-BLOCKS-EXTERN
// RUN: %clang_cc1 -triple x86_64-windows -fblocks -fdeclspec -DBLOCKS_NOT_IN_BLOCKS_EXTERN_DLLIMPORT -Os -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-BLOCKS-NOT-IN-BLOCKS-EXTERN-DLLIMPORT
// RUN: %clang_cc1 -triple x86_64-windows -fblocks -fdeclspec -DBLOCKS_NOT_IN_BLOCKS_DLLIMPORT -Os -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-BLOCKS-NOT-IN-BLOCKS-DLLIMPORT
@@ -70,6 +76,7 @@ int (*g(void))(void) {
// CHECK-BLOCKS-IN-BLOCKS-DECL: @_NSConcreteStackBlock = external dso_local dllexport global ptr
// CHECK-BLOCKS-IN-BLOCKS-DEFN: @_NSConcreteStackBlock = dso_local dllexport global [5 x i32]
// CHECK-BLOCKS-NOT-IN-BLOCKS: @_NSConcreteStackBlock = external dllimport global ptr
+// CHECK-BLOCKS-NOT-IN-STATIC-BLOCKS: @_NSConcreteStackBlock = external global ptr
// CHECK-BLOCKS-NOT-IN-BLOCKS-EXTERN: @_NSConcreteStackBlock = external dllimport global ptr
// CHECK-BLOCKS-NOT-IN-BLOCKS-EXTERN-DLLIMPORT: @_NSConcreteStackBlock = external dllimport global ptr
// CHECK-BLOCKS-NOT-IN-BLOCKS-DLLIMPORT: @_NSConcreteStackBlock = external dllimport global ptr
|
4e0eb2c
to
33f361f
Compare
I thought the Windows linker actually can handle statically linking dllimported symbols this (maybe with a warning?). The other options you mention ( |
The other way works with warnings and some performance loss and code bloat (linking code designed for DLL as static). So far I've always mandated dynamic linking for BlocksRuntime on Windows within the Swift toolchain and by the Swift toolchain. You are correct that the |
Do you anticipate the clang driver ever adding the libclosure runtime to the link line automatically? If we do, would this flag control the behavior of that? |
I can see that as being useful certainly. |
@efriedma-quic any thoughts on that? I think that this is ready to be merged. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add HelpText for the new option. Maybe mention in that text that it currently doesn't affect linking.
Please add a release note.
Otherwise looks fine.
When building on Windows, dealing with the BlocksRuntime is slightly more complicated. As we are not guaranteed a formward declaration for the blocks runtime ABI symbols, we may generate the declarations for them. In order to properly link against the well-known types, we always annotated them as `__declspec(dllimport)`. This would require the dynamic linking of the blocks runtime under all conditions. However, this is the only the only possible way to us the library. We may be building a fully sealed (static) executable. In such a case, the well known symbols should not be marked as `dllimport` as they are assumed to be statically available with the static linking to the BlocksRuntime. Introduce a new driver/cc1 option `-static-libclosure` which mirrors the myriad of similar options (`-static-libgcc`, `-static-libstdc++`, -static-libsan`, etc).
33f361f
to
0047041
Compare
When building on Windows, dealing with the BlocksRuntime is slightly more complicated. As we are not guaranteed a formward declaration for the blocks runtime ABI symbols, we may generate the declarations for them. In order to properly link against the well-known types, we always annotated them as `__declspec(dllimport)`. This would require the dynamic linking of the blocks runtime under all conditions. However, this is the only the only possible way to us the library. We may be building a fully sealed (static) executable. In such a case, the well known symbols should not be marked as `dllimport` as they are assumed to be statically available with the static linking to the BlocksRuntime. Introduce a new driver/cc1 option `-static-libclosure` which mirrors the myriad of similar options (`-static-libgcc`, `-static-libstdc++`, -static-libsan`, etc). (cherry picked from commit 1901f4a)
When building on Windows, dealing with the BlocksRuntime is slightly more complicated. As we are not guaranteed a formward declaration for the blocks runtime ABI symbols, we may generate the declarations for them. In order to properly link against the well-known types, we always annotated them as `__declspec(dllimport)`. This would require the dynamic linking of the blocks runtime under all conditions. However, this is the only the only possible way to us the library. We may be building a fully sealed (static) executable. In such a case, the well known symbols should not be marked as `dllimport` as they are assumed to be statically available with the static linking to the BlocksRuntime. Introduce a new driver/cc1 option `-static-libclosure` which mirrors the myriad of similar options (`-static-libgcc`, `-static-libstdc++`, -static-libsan`, etc).
Hi, I'm not sure where to move your addition in the ReleaseNotes, but I'm pretty sure it shouldn't be in the Static Analyzer section. |
@steakhal bleh, is the "New Features" a sub item of "Static Analyzer"? |
Ah you are right. Its at the right place. Nvm. |
When building on Windows, dealing with the BlocksRuntime is slightly more complicated. As we are not guaranteed a formward declaration for the blocks runtime ABI symbols, we may generate the declarations for them. In order to properly link against the well-known types, we always annotated them as
__declspec(dllimport)
. This would require the dynamic linking of the blocks runtime under all conditions. However, this is the only the only possible way to us the library. We may be building a fully sealed (static) executable. In such a case, the well known symbols should not be marked asdllimport
as they are assumed to be statically available with the static linking to the BlocksRuntime.Introduce a new driver/cc1 option
-static-libclosure
which mirrors the myriad of similar options (-static-libgcc
,-static-libstdc++
, -static-libsan`, etc).