[clang] b87a120 - [ObjC] Encode pointers to C++ classes as "^v" if the encoded string
Akira Hatanaka via cfe-commits
cfe-commits at lists.llvm.org
Thu Feb 18 09:38:38 PST 2021
Author: Akira Hatanaka
Date: 2021-02-18T09:38:26-08:00
New Revision: b87a120820989844dc206c66bd0272b5238a14d1
URL: https://github.com/llvm/llvm-project/commit/b87a120820989844dc206c66bd0272b5238a14d1
DIFF: https://github.com/llvm/llvm-project/commit/b87a120820989844dc206c66bd0272b5238a14d1.diff
LOG: [ObjC] Encode pointers to C++ classes as "^v" if the encoded string
would otherwise include template specialization types
This helps reduce the size of the encoded C++ type strings in the binary.
This is enabled by default only on Darwin, but can be enabled/disabled
via command line options.
rdar://63288571
Differential Revision: https://reviews.llvm.org/D96816
Added:
clang/test/Driver/objc-encode-cxx-class-template-spec.m
Modified:
clang/include/clang/Basic/LangOptions.def
clang/include/clang/Driver/Options.td
clang/lib/AST/ASTContext.cpp
clang/lib/Driver/ToolChains/Clang.cpp
clang/test/CodeGenObjCXX/encode.mm
Removed:
################################################################################
diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def
index e24408985dec..346638549719 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -98,6 +98,8 @@ BENIGN_LANGOPT(ObjCDefaultSynthProperties , 1, 0,
"Objective-C auto-synthesized properties")
BENIGN_LANGOPT(EncodeExtendedBlockSig , 1, 0,
"Encoding extended block type signature")
+BENIGN_LANGOPT(EncodeCXXClassTemplateSpec , 1, 0,
+ "Fully encode c++ class template specialization")
BENIGN_LANGOPT(ObjCInferRelatedResultType , 1, 1,
"Objective-C related result type inference")
LANGOPT(AppExt , 1, 0, "Objective-C App Extension")
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 0e09958b36e1..efb1f2e2288f 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -2098,6 +2098,10 @@ def fno_wrapv : Flag<["-"], "fno-wrapv">, Group<f_Group>;
def fobjc_arc : Flag<["-"], "fobjc-arc">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Synthesize retain and release calls for Objective-C pointers">;
def fno_objc_arc : Flag<["-"], "fno-objc-arc">, Group<f_Group>;
+defm objc_encode_cxx_class_template_spec : BoolFOption<"objc-encode-cxx-class-template-spec",
+ LangOpts<"EncodeCXXClassTemplateSpec">, DefaultFalse,
+ PosFlag<SetTrue, [CC1Option], "Fully encode c++ class template specialization">,
+ NegFlag<SetFalse>>;
defm objc_convert_messages_to_runtime_calls : BoolFOption<"objc-convert-messages-to-runtime-calls",
CodeGenOpts<"ObjCConvertMessagesToRuntimeCalls">, DefaultTrue,
NegFlag<SetFalse, [CC1Option]>, PosFlag<SetTrue>>;
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index f97d89c14d70..33e247d88c9d 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -7352,6 +7352,40 @@ static void EncodeBitField(const ASTContext *Ctx, std::string& S,
S += llvm::utostr(FD->getBitWidthValue(*Ctx));
}
+// Helper function for determining whether the encoded type string would include
+// a template specialization type.
+static bool hasTemplateSpecializationInEncodedString(const Type *T,
+ bool VisitBasesAndFields) {
+ T = T->getBaseElementTypeUnsafe();
+
+ if (auto *PT = T->getAs<PointerType>())
+ return hasTemplateSpecializationInEncodedString(
+ PT->getPointeeType().getTypePtr(), false);
+
+ auto *CXXRD = T->getAsCXXRecordDecl();
+
+ if (!CXXRD)
+ return false;
+
+ if (isa<ClassTemplateSpecializationDecl>(CXXRD))
+ return true;
+
+ if (!CXXRD->hasDefinition() || !VisitBasesAndFields)
+ return false;
+
+ for (auto B : CXXRD->bases())
+ if (hasTemplateSpecializationInEncodedString(B.getType().getTypePtr(),
+ true))
+ return true;
+
+ for (auto *FD : CXXRD->fields())
+ if (hasTemplateSpecializationInEncodedString(FD->getType().getTypePtr(),
+ true))
+ return true;
+
+ return false;
+}
+
// FIXME: Use SmallString for accumulating string.
void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string &S,
const ObjCEncOptions Options,
@@ -7444,6 +7478,15 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string &S,
S += '@';
return;
}
+ // If the encoded string for the class includes template names, just emit
+ // "^v" for pointers to the class.
+ if (getLangOpts().CPlusPlus &&
+ (!getLangOpts().EncodeCXXClassTemplateSpec &&
+ hasTemplateSpecializationInEncodedString(
+ RTy, Options.ExpandPointedToStructures()))) {
+ S += "^v";
+ return;
+ }
// fall through...
}
S += '^';
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 2fe5bbe2f06c..ae7a8227d304 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -5992,6 +5992,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
RenderObjCOptions(TC, D, RawTriple, Args, Runtime, rewriteKind != RK_None,
Input, CmdArgs);
+ if (types::isObjC(Input.getType()) &&
+ Args.hasFlag(options::OPT_fobjc_encode_cxx_class_template_spec,
+ options::OPT_fno_objc_encode_cxx_class_template_spec,
+ !Runtime.isNeXTFamily()))
+ CmdArgs.push_back("-fobjc-encode-cxx-class-template-spec");
+
if (Args.hasFlag(options::OPT_fapplication_extension,
options::OPT_fno_application_extension, false))
CmdArgs.push_back("-fapplication-extension");
diff --git a/clang/test/CodeGenObjCXX/encode.mm b/clang/test/CodeGenObjCXX/encode.mm
index e5e1123c2dc8..f6365ddb33f1 100644
--- a/clang/test/CodeGenObjCXX/encode.mm
+++ b/clang/test/CodeGenObjCXX/encode.mm
@@ -1,5 +1,6 @@
-// RUN: %clang_cc1 -Wno-objc-root-class -std=gnu++98 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck --check-prefixes CHECK,CHECKCXX98 %s
-// RUN: %clang_cc1 -Wno-objc-root-class -std=gnu++20 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck --check-prefixes CHECK,CHECKCXX20 %s
+// RUN: %clang_cc1 -Wno-objc-root-class -std=gnu++98 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck --check-prefixes CHECK,CHECKCXX98,CHECK-NO-TEMP-SPEC %s
+// RUN: %clang_cc1 -Wno-objc-root-class -std=gnu++20 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck --check-prefixes CHECK,CHECKCXX20,CHECK-NO-TEMP-SPEC %s
+// RUN: %clang_cc1 -Wno-objc-root-class -std=gnu++20 %s -triple=x86_64-apple-darwin10 -fobjc-encode-cxx-class-template-spec -emit-llvm -o - | FileCheck --check-prefixes CHECK,CHECKCXX20,CHECK-TEMP-SPEC %s
// CHECK: v17 at 0:8{vector<float, float, float>=}16
// CHECK: {vector<float, float, float>=}
@@ -260,3 +261,82 @@ @implementation N
extern const char x[] = @encode(I);
}
#endif
+
+namespace test_cxx_template_specialization {
+template <class T>
+struct B0 {
+ T a;
+};
+struct D0 : B0<int> {};
+struct D1 : D0 {};
+struct D2 : virtual B0<int> {};
+struct S0 {
+ B0<int> a;
+};
+struct S1 {
+ B0<int> *a;
+};
+struct S2 {
+ S1 *a;
+};
+template <class T>
+union U0 {
+ T a;
+};
+typedef B0<int> TD0;
+typedef B0<int> *Array0[4];
+
+template <class T>
+struct Outer0 {
+ struct Inner0 {
+ int a;
+ };
+ template <class T1>
+ struct Inner1 {
+ T a;
+ T1 b;
+ };
+};
+
+// CHECK: @[[STR22:.*]] = {{.*}} [12 x i8] c"{B0<int>=i}\00"
+// CHECK: @_ZN32test_cxx_template_specialization2b0E = {{.*}} ([12 x i8], [12 x i8]* @[[STR22]], i32 0, i32 0)
+// CHECK-NO-TEMP-SPEC: @[[STR23:.*]] = {{.*}} [3 x i8] c"^v\00"
+// CHECK-NO-TEMP-SPEC: @_ZN32test_cxx_template_specialization3b01E = {{.*}} ([3 x i8], [3 x i8]* @[[STR23]], i32 0, i32 0)
+// CHECK-TEMP-SPEC: @[[STR23:.*]] = {{.*}} [13 x i8] c"^{B0<int>=i}\00"
+// CHECK-TEMP-SPEC: @_ZN32test_cxx_template_specialization3b01E = {{.*}} ([13 x i8], [13 x i8]* @[[STR23]], i32 0, i32 0)
+// CHECK-NO-TEMP-SPEC: @_ZN32test_cxx_template_specialization3b02E = {{.*}} ([3 x i8], [3 x i8]* @[[STR23]], i32 0, i32 0)
+// CHECK-NO-TEMP-SPEC: @_ZN32test_cxx_template_specialization2d0E = {{.*}} ([3 x i8], [3 x i8]* @[[STR23]], i32 0, i32 0)
+// CHECK-NO-TEMP-SPEC: @_ZN32test_cxx_template_specialization2d1E = {{.*}} ([3 x i8], [3 x i8]* @[[STR23]], i32 0, i32 0)
+// CHECK-NO-TEMP-SPEC: @_ZN32test_cxx_template_specialization2d2E = {{.*}} ([3 x i8], [3 x i8]* @[[STR23]], i32 0, i32 0)
+// CHECK: @[[STR24:.*]] = {{.*}} [7 x i8] c"^^{D2}\00"
+// CHECK: @_ZN32test_cxx_template_specialization3d21E = {{.*}} ([7 x i8], [7 x i8]* @[[STR24]], i32 0, i32 0)
+// CHECK-NO-TEMP-SPEC: @_ZN32test_cxx_template_specialization2s0E = {{.*}} ([3 x i8], [3 x i8]* @[[STR23]], i32 0, i32 0)
+// CHECK-NO-TEMP-SPEC: @_ZN32test_cxx_template_specialization2s1E = {{.*}} ([3 x i8], [3 x i8]* @[[STR23]], i32 0, i32 0)
+// CHECK: @[[STR25:.*]] = {{.*}} [12 x i8] c"^{S2=^{S1}}\00"
+// CHECK: @_ZN32test_cxx_template_specialization2s2E = {{.*}} ([12 x i8], [12 x i8]* @[[STR25]], i32 0, i32 0)
+// CHECK-NO-TEMP-SPEC: @_ZN32test_cxx_template_specialization2u0E = {{.*}} ([3 x i8], [3 x i8]* @[[STR23]], i32 0, i32 0)
+// CHECK-NO-TEMP-SPEC: @_ZN32test_cxx_template_specialization3td0E = {{.*}} ([3 x i8], [3 x i8]* @[[STR23]], i32 0, i32 0)
+// CHECK-NO-TEMP-SPEC: @[[STR26:.*]] = {{.*}} [6 x i8] c"[4^v]\00"
+// CHECK-NO-TEMP-SPEC: @_ZN32test_cxx_template_specialization2a0E = {{.*}} ([6 x i8], [6 x i8]* @[[STR26]], i32 0, i32 0)
+// CHECK: @[[STR27:.*]] = {{.*}} [11 x i8] c"^{Inner0=}\00"
+// CHECK: @_ZN32test_cxx_template_specialization6inner0E = {{.*}} ([11 x i8], [11 x i8]* @[[STR27]], i32 0, i32 0)
+// CHECK-NO-TEMP-SPEC: @_ZN32test_cxx_template_specialization6inner1E = {{.*}} ([3 x i8], [3 x i8]* @.str.23, i32 0, i32 0)
+// CHECK-TEMP-SPEC: @[[STR34:.*]] = {{.*}} [18 x i8] c"^{Inner1<float>=}\00"
+// CHECK-TEMP-SPEC: @_ZN32test_cxx_template_specialization6inner1E = {{.*}} ([18 x i8], [18 x i8]* @[[STR34]], i32 0, i32 0)
+
+const char *b0 = @encode(B0<int>);
+const char *b01 = @encode(B0<int> *);
+const char *b02 = @encode(B0<int> &);
+const char *d0 = @encode(D0 *);
+const char *d1 = @encode(D1 *);
+const char *d2 = @encode(D2 *);
+const char *d21 = @encode(D2 **);
+const char *s0 = @encode(S0 *);
+const char *s1 = @encode(S1 *);
+const char *s2 = @encode(S2 *);
+const char *u0 = @encode(U0<int> *);
+const char *td0 = @encode(TD0 *);
+const char *a0 = @encode(Array0);
+const char *inner0 = @encode(Outer0<int>::Inner0 *);
+const char *inner1 = @encode(Outer0<int>::Inner1<float> *);
+}
diff --git a/clang/test/Driver/objc-encode-cxx-class-template-spec.m b/clang/test/Driver/objc-encode-cxx-class-template-spec.m
new file mode 100644
index 000000000000..23d114f1a4fa
--- /dev/null
+++ b/clang/test/Driver/objc-encode-cxx-class-template-spec.m
@@ -0,0 +1,7 @@
+// RUN: %clang -target arm64-apple-ios11 -### %s -o - 2>&1 | FileCheck -check-prefix=DISABLE-ENC %s
+// RUN: %clang -target arm64-apple-ios11 -fobjc-encode-cxx-class-template-spec -### %s -o - 2>&1 | FileCheck -check-prefix=ENABLE-ENC %s
+// RUN: %clang -target x86_64-linux-gnu -fobjc-runtime=gnustep -### %s -o - 2>&1 | FileCheck -check-prefix=ENABLE-ENC %s
+// RUN: %clang -target x86_64-linux-gnu -fobjc-runtime=gnustep -fno-objc-encode-cxx-class-template-spec -### %s -o - 2>&1 | FileCheck -check-prefix=DISABLE-ENC %s
+
+// DISABLE-ENC-NOT: -fobjc-encode-cxx-class-template-spec
+// ENABLE-ENC: -fobjc-encode-cxx-class-template-spec
More information about the cfe-commits
mailing list