Skip to content

[CodeGen] Add a flag to disable emitting block signature strings #96944

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 9, 2024
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
5 changes: 5 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,11 @@ New Compiler Flags
- ``-Wc++2c-compat`` group was added to help migrating existing codebases
to upcoming C++26.

- ``-fdisable-block-signature-string`` instructs clang not to emit the signature
string for blocks. Disabling the string can potentially break existing code
that relies on it. Users should carefully consider this possibiilty when using
the flag.

Deprecated Compiler Flags
-------------------------

Expand Down
6 changes: 6 additions & 0 deletions clang/docs/UsersManual.rst
Original file line number Diff line number Diff line change
Expand Up @@ -913,6 +913,12 @@ Clang options that don't fit neatly into other categories.
binary compatibility issues on older x86_64 targets, however, so use it with
caution.

.. option:: -fdisable-block-signature-string

Instruct clang not to emit the signature string for blocks. Disabling the
string can potentially break existing code that relies on it. Users should
carefully consider this possibiilty when using the flag.

.. _configuration-files:

Configuration files
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/CodeGenOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ CODEGENOPT(NoImplicitFloat , 1, 0) ///< Set when -mno-implicit-float is enable
CODEGENOPT(NullPointerIsValid , 1, 0) ///< Assume Null pointer deference is defined.
CODEGENOPT(OpenCLCorrectlyRoundedDivSqrt, 1, 0) ///< -cl-fp32-correctly-rounded-divide-sqrt
CODEGENOPT(HIPCorrectlyRoundedDivSqrt, 1, 1) ///< -fno-hip-fp32-correctly-rounded-divide-sqrt
CODEGENOPT(DisableBlockSignatureString, 1, 0) ///< Set when -fdisable-block-signature-string is enabled.
CODEGENOPT(HIPSaveKernelArgName, 1, 0) ///< Set when -fhip-kernel-arg-name is enabled.
CODEGENOPT(UniqueInternalLinkageNames, 1, 0) ///< Internal Linkage symbols get unique names.
CODEGENOPT(SplitMachineFunctions, 1, 0) ///< Split machine functions using profile information.
Expand Down
5 changes: 5 additions & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -3477,6 +3477,11 @@ defm objc_avoid_heapify_local_blocks : BoolFOption<"objc-avoid-heapify-local-blo
PosFlag<SetTrue, [], [ClangOption], "Try">,
NegFlag<SetFalse, [], [ClangOption], "Don't try">,
BothFlags<[], [CC1Option], " to avoid heapifying local blocks">>;
defm disable_block_signature_string : BoolFOption<"disable-block-signature-string",
CodeGenOpts<"DisableBlockSignatureString">, DefaultFalse,
PosFlag<SetTrue, [], [ClangOption], "Disable">,
NegFlag<SetFalse, [], [ClangOption], "Don't disable">,
BothFlags<[], [CC1Option], " block signature string)">>;

def fomit_frame_pointer : Flag<["-"], "fomit-frame-pointer">, Group<f_Group>,
Visibility<[ClangOption, FlangOption]>,
Expand Down
31 changes: 21 additions & 10 deletions clang/lib/CodeGen/CGBlocks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,11 +121,15 @@ static std::string getBlockDescriptorName(const CGBlockInfo &BlockInfo,
Name += "_";
}

std::string TypeAtEncoding =
CGM.getContext().getObjCEncodingForBlock(BlockInfo.getBlockExpr());
/// Replace occurrences of '@' with '\1'. '@' is reserved on ELF platforms as
/// a separator between symbol name and symbol version.
std::replace(TypeAtEncoding.begin(), TypeAtEncoding.end(), '@', '\1');
std::string TypeAtEncoding;

if (!CGM.getCodeGenOpts().DisableBlockSignatureString) {
TypeAtEncoding =
CGM.getContext().getObjCEncodingForBlock(BlockInfo.getBlockExpr());
/// Replace occurrences of '@' with '\1'. '@' is reserved on ELF platforms
/// as a separator between symbol name and symbol version.
std::replace(TypeAtEncoding.begin(), TypeAtEncoding.end(), '@', '\1');
}
Name += "e" + llvm::to_string(TypeAtEncoding.size()) + "_" + TypeAtEncoding;
Name += "l" + CGM.getObjCRuntime().getRCBlockLayoutStr(CGM, BlockInfo);
return Name;
Expand Down Expand Up @@ -201,9 +205,13 @@ static llvm::Constant *buildBlockDescriptor(CodeGenModule &CGM,
}

// Signature. Mandatory ObjC-style method descriptor @encode sequence.
std::string typeAtEncoding =
CGM.getContext().getObjCEncodingForBlock(blockInfo.getBlockExpr());
elements.add(CGM.GetAddrOfConstantCString(typeAtEncoding).getPointer());
if (CGM.getCodeGenOpts().DisableBlockSignatureString) {
elements.addNullPointer(i8p);
} else {
std::string typeAtEncoding =
CGM.getContext().getObjCEncodingForBlock(blockInfo.getBlockExpr());
elements.add(CGM.GetAddrOfConstantCString(typeAtEncoding).getPointer());
}

// GC layout.
if (C.getLangOpts().ObjC) {
Expand Down Expand Up @@ -814,7 +822,8 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
descriptor = buildBlockDescriptor(CGM, blockInfo);

// Compute the initial on-stack block flags.
flags = BLOCK_HAS_SIGNATURE;
if (!CGM.getCodeGenOpts().DisableBlockSignatureString)
flags = BLOCK_HAS_SIGNATURE;
if (blockInfo.HasCapturedVariableLayout)
flags |= BLOCK_HAS_EXTENDED_LAYOUT;
if (blockInfo.NeedsCopyDispose)
Expand Down Expand Up @@ -1300,7 +1309,9 @@ static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM,
fields.add(CGM.getNSConcreteGlobalBlock());

// __flags
BlockFlags flags = BLOCK_IS_GLOBAL | BLOCK_HAS_SIGNATURE;
BlockFlags flags = BLOCK_IS_GLOBAL;
if (!CGM.getCodeGenOpts().DisableBlockSignatureString)
flags |= BLOCK_HAS_SIGNATURE;
if (blockInfo.UsesStret)
flags |= BLOCK_USE_STRET;

Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5751,6 +5751,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_fexperimental_omit_vtable_rtti,
options::OPT_fno_experimental_omit_vtable_rtti);

Args.AddLastArg(CmdArgs, options::OPT_fdisable_block_signature_string,
options::OPT_fno_disable_block_signature_string);

// Handle segmented stacks.
Args.addOptInFlag(CmdArgs, options::OPT_fsplit_stack,
options::OPT_fno_split_stack);
Expand Down
13 changes: 10 additions & 3 deletions clang/test/CodeGen/blocks.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
// RUN: %clang_cc1 -triple i386-unknown-unknown %s -emit-llvm -Wno-strict-prototypes -o - -fblocks | FileCheck %s
// RUN: %clang_cc1 -triple i386-unknown-unknown %s -emit-llvm -Wno-strict-prototypes -o - -fblocks | FileCheck --check-prefix=CHECK --check-prefix=SIG_STR %s
// RUN: %clang_cc1 -triple i386-unknown-unknown %s -emit-llvm -Wno-strict-prototypes -o - -fblocks -fdisable-block-signature-string | FileCheck --check-prefix=CHECK --check-prefix=NO_SIG_STR %s

// CHECK: @{{.*}} = internal constant { i32, i32, ptr, ptr, ptr, ptr } { i32 0, i32 24, ptr @__copy_helper_block_4_20r, ptr @__destroy_helper_block_4_20r, ptr @{{.*}}, ptr null }, align 4
// CHECK: @[[BLOCK_DESCRIPTOR_TMP21:.*]] = internal constant { i32, i32, ptr, ptr, ptr, ptr } { i32 0, i32 24, ptr @__copy_helper_block_4_20r, ptr @__destroy_helper_block_4_20r, ptr @{{.*}}, ptr null }, align 4
// SIG_STR: @[[STR:.*]] = private unnamed_addr constant [6 x i8] c"v4@?0\00", align 1
// SIG_STR: @{{.*}} = internal constant { ptr, i32, i32, ptr, ptr } { ptr @_NSConcreteGlobalBlock, i32 1342177280, i32 0, ptr @f_block_invoke, ptr @{{.*}} }, align 4
// NO_SIG_STR: @{{.*}} = internal constant { ptr, i32, i32, ptr, ptr } { ptr @_NSConcreteGlobalBlock, i32 268435456, i32 0, ptr @f_block_invoke, ptr @{{.*}} }, align 4

// SIG_STR: @{{.*}} = internal constant { i32, i32, ptr, ptr, ptr, ptr } { i32 0, i32 24, ptr @__copy_helper_block_4_20r, ptr @__destroy_helper_block_4_20r, ptr @[[STR]], ptr null }, align 4
// SIG_STR: @[[BLOCK_DESCRIPTOR_TMP21:.*]] = internal constant { i32, i32, ptr, ptr, ptr, ptr } { i32 0, i32 24, ptr @__copy_helper_block_4_20r, ptr @__destroy_helper_block_4_20r, ptr @[[STR]], ptr null }, align 4
// NO_SIG_STR: @{{.*}} = internal constant { i32, i32, ptr, ptr, ptr, ptr } { i32 0, i32 24, ptr @__copy_helper_block_4_20r, ptr @__destroy_helper_block_4_20r, ptr null, ptr null }, align 4
// NO_SIG_STR: @[[BLOCK_DESCRIPTOR_TMP21:.*]] = internal constant { i32, i32, ptr, ptr, ptr, ptr } { i32 0, i32 24, ptr @__copy_helper_block_4_20r, ptr @__destroy_helper_block_4_20r, ptr null, ptr null }, align 4

void (^f)(void) = ^{};

Expand Down
11 changes: 9 additions & 2 deletions clang/test/CodeGenObjC/blocks.m
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
// RUN: %clang_cc1 -triple i386-apple-darwin9 -fobjc-runtime=macosx-fragile-10.5 -emit-llvm -fblocks -Wno-strict-prototypes -o - %s | FileCheck %s
// RUN: %clang_cc1 -triple i386-apple-darwin9 -fobjc-runtime=macosx-fragile-10.5 -emit-llvm -fblocks -Wno-strict-prototypes -o - %s | FileCheck --check-prefix=CHECK --check-prefix=SIG_STR %s
// RUN: %clang_cc1 -triple i386-apple-darwin9 -fobjc-runtime=macosx-fragile-10.5 -emit-llvm -fblocks -Wno-strict-prototypes -fdisable-block-signature-string -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NO_SIG_STR %s

// Check that there is only one capture (20o) in the copy/dispose function
// names.

// CHECK: @[[BLOCK_DESCRIPTOR0:.*]] = linkonce_odr hidden unnamed_addr constant { i32, i32, ptr, ptr, ptr, i32 } { i32 0, i32 28, ptr @__copy_helper_block_4_20o, ptr @__destroy_helper_block_4_20o, ptr @{{.*}}, i32 512 },
// SIG_STR: @[[STR3:.*]] = private unnamed_addr constant [6 x i8] c"v4@?0\00", align 1
// SIG_STR: @[[BLOCK_DESCRIPTOR0:"__block_descriptor_28_4_20o_e5_v4\\01\?0l"]] = linkonce_odr hidden unnamed_addr constant { i32, i32, ptr, ptr, ptr, i32 } { i32 0, i32 28, ptr @__copy_helper_block_4_20o, ptr @__destroy_helper_block_4_20o, ptr @[[STR3]], i32 512 },
// NO_SIG_STR: @[[BLOCK_DESCRIPTOR0:__block_descriptor_28_4_20o_e0_l]] = linkonce_odr hidden unnamed_addr constant { i32, i32, ptr, ptr, ptr, i32 } { i32 0, i32 28, ptr @__copy_helper_block_4_20o, ptr @__destroy_helper_block_4_20o, ptr null, i32 512 },


void (^gb0)(void);

Expand Down Expand Up @@ -132,6 +136,9 @@ void test5(A *a) {
}

// CHECK-LABEL: define void @test5(
// CHECK: %[[FLAGS:.*]] = getelementptr inbounds <{ ptr, i32, i32, ptr, ptr, ptr, ptr }>, ptr %{{.*}}, i32 0, i32 1
// SIG_STR: store i32 -1040187392, ptr %[[FLAGS]], align 4
// NO_SIG_STR: store i32 -2113929216, ptr %[[FLAGS]], align 4
// CHECK: %[[V0:.*]] = getelementptr inbounds <{ ptr, i32, i32, ptr, ptr, ptr, ptr }>, ptr %{{.*}}, i32 0, i32 4
// CHECK: store ptr @[[BLOCK_DESCRIPTOR0]], ptr %[[V0]],

Expand Down
Loading