[prev in list] [next in list] [prev in thread] [next in thread]
List: cfe-commits
Subject: [PATCH] D53674: [CodeGen] Fix assertion on referencing constexpr Obj-C object with ARC.
From: Volodymyr Sapsai via Phabricator via cfe-commits <cfe-commits () lists ! llvm ! org>
Date: 2018-10-31 23:36:56
Message-ID: 36f0d8ef58d744c5931d66323eb52135 () localhost ! localdomain
[Download RAW message or body]
vsapsai updated this revision to Diff 172049.
vsapsai added a comment.
- Rename `EmitConstant` to `emitScalarConstant`.
- Tweak comment to be explicitly about intended IR code, not about Obj-C++ =
code.
https://reviews.llvm.org/D53674
Files:
clang/lib/CodeGen/CGExpr.cpp
clang/lib/CodeGen/CGExprScalar.cpp
clang/lib/CodeGen/CGObjC.cpp
clang/lib/CodeGen/CodeGenFunction.h
clang/test/CodeGenObjCXX/arc-constexpr.mm
["D53674.172049.patch" (text/x-patch)]
Index: clang/test/CodeGenObjCXX/arc-constexpr.mm
===================================================================
--- clang/test/CodeGenObjCXX/arc-constexpr.mm
+++ clang/test/CodeGenObjCXX/arc-constexpr.mm
@@ -1,18 +1,51 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-arc -o - \
-std=c++11 %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 \
-emit-llvm -fobjc-arc -fobjc-runtime-has-weak -o - -std=c++11 %s | FileCheck %s
// CHECK: %[[TYPE:[a-z0-9]+]] = type opaque
// CHECK: @[[CFSTRING:[a-z0-9_]+]] = private global %struct.__NSConstantString_tag
+@class NSString;
-// CHECK: define void @_Z5test1v
+// CHECK-LABEL: define void @_Z5test1v
// CHECK: %[[ALLOCA:[A-Z]+]] = alloca %[[TYPE]]*
// CHECK: %[[V0:[0-9]+]] = call i8* @objc_retain(i8* bitcast \
(%struct.__NSConstantString_tag* @[[CFSTRING]] // CHECK: %[[V1:[0-9]+]] = bitcast \
i8* %[[V0]] to %[[TYPE]]* // CHECK: store %[[TYPE]]* %[[V1]], %[[TYPE]]** \
%[[ALLOCA]] // CHECK: %[[V2:[0-9]+]] = bitcast %[[TYPE]]** %[[ALLOCA]]
// CHECK: call void @objc_storeStrong(i8** %[[V2]], i8* null)
-
-@class NSString;
-
void test1() {
constexpr NSString *S = @"abc";
}
+
+// CHECK-LABEL: define void @_Z5test2v
+// CHECK: %[[CONST:[a-zA-Z]+]] = alloca %[[TYPE]]*
+// CHECK: %[[REF_CONST:[a-zA-Z]+]] = alloca %[[TYPE]]*
+// CHECK: %[[V0:[0-9]+]] = call i8* @objc_retain(i8* bitcast \
(%struct.__NSConstantString_tag* @[[CFSTRING]] +// CHECK-NEXT: %[[V1:[0-9]+]] = \
bitcast i8* %[[V0]] to %[[TYPE]]* +// CHECK-NEXT: store %[[TYPE]]* %[[V1]], \
%[[TYPE]]** %[[CONST]] +// CHECK: %[[V2:[0-9]+]] = call i8* @objc_retain(i8* \
bitcast (%struct.__NSConstantString_tag* @[[CFSTRING]] +// CHECK-NEXT: %[[V3:[0-9]+]] \
= bitcast i8* %[[V2]] to %[[TYPE]]* +// CHECK-NEXT: store %[[TYPE]]* %[[V3]], \
%[[TYPE]]** %[[REF_CONST]] +// CHECK: %[[V4:[0-9]+]] = bitcast %[[TYPE]]** \
%[[REF_CONST]] +// CHECK-NEXT: call void @objc_storeStrong(i8** %[[V4]], i8* null)
+// CHECK: %[[V5:[0-9]+]] = bitcast %[[TYPE]]** %[[CONST]]
+// CHECK-NEXT: call void @objc_storeStrong(i8** %[[V5]], i8* null)
+void test2() {
+ constexpr NSString *Const = @"abc";
+ // In IR RefConst should be initialized with Const initializer instead of
+ // reading from variable.
+ NSString* RefConst = Const;
+}
+
+// CHECK-LABEL: define void @_Z5test3v
+// CHECK: %[[WEAK_CONST:[a-zA-Z]+]] = alloca %[[TYPE]]*
+// CHECK: %[[REF_WEAK_CONST:[a-zA-Z]+]] = alloca %[[TYPE]]*
+// CHECK: %[[V0:[0-9]+]] = bitcast %[[TYPE]]** %[[WEAK_CONST]]
+// CHECK-NEXT: %[[V1:[0-9]+]] = call i8* @objc_initWeak(i8** %[[V0]], i8* bitcast \
(%struct.__NSConstantString_tag* @[[CFSTRING]] +// CHECK: store %[[TYPE]]* \
bitcast (%struct.__NSConstantString_tag* @[[CFSTRING]] to %[[TYPE]]*), %[[TYPE]]** \
%[[REF_WEAK_CONST]] +// CHECK: %[[V2:[0-9]+]] = bitcast %[[TYPE]]** \
%[[REF_WEAK_CONST]] +// CHECK-NEXT: call void @objc_storeStrong(i8** %[[V2]], i8* \
null) +// CHECK: %[[V3:[0-9]+]] = bitcast %[[TYPE]]** %[[WEAK_CONST]]
+// CHECK-NEXT: call void @objc_destroyWeak(i8** %[[V3]])
+void test3() {
+ __weak constexpr NSString *WeakConst = @"abc";
+ NSString* RefWeakConst = WeakConst;
+}
Index: clang/lib/CodeGen/CodeGenFunction.h
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.h
+++ clang/lib/CodeGen/CodeGenFunction.h
@@ -3524,6 +3524,7 @@
ConstantEmission tryEmitAsConstant(DeclRefExpr *refExpr);
ConstantEmission tryEmitAsConstant(const MemberExpr *ME);
+ llvm::Value *emitScalarConstant(const ConstantEmission &Constant, Expr *E);
RValue EmitPseudoObjectRValue(const PseudoObjectExpr *e,
AggValueSlot slot = AggValueSlot::ignored());
Index: clang/lib/CodeGen/CGObjC.cpp
===================================================================
--- clang/lib/CodeGen/CGObjC.cpp
+++ clang/lib/CodeGen/CGObjC.cpp
@@ -2446,26 +2446,35 @@
EHStack.pushCleanup<CallObjCMRRAutoreleasePoolObject>(NormalCleanup, Ptr);
}
-static TryEmitResult tryEmitARCRetainLoadOfScalar(CodeGenFunction &CGF,
- LValue lvalue,
- QualType type) {
- switch (type.getObjCLifetime()) {
+static bool shouldRetainObjCLifetime(Qualifiers::ObjCLifetime lifetime) {
+ switch (lifetime) {
case Qualifiers::OCL_None:
case Qualifiers::OCL_ExplicitNone:
case Qualifiers::OCL_Strong:
case Qualifiers::OCL_Autoreleasing:
- return TryEmitResult(CGF.EmitLoadOfLValue(lvalue,
- SourceLocation()).getScalarVal(),
- false);
+ return true;
case Qualifiers::OCL_Weak:
- return TryEmitResult(CGF.EmitARCLoadWeakRetained(lvalue.getAddress()),
- true);
+ return false;
}
llvm_unreachable("impossible lifetime!");
}
+static TryEmitResult tryEmitARCRetainLoadOfScalar(CodeGenFunction &CGF,
+ LValue lvalue,
+ QualType type) {
+ llvm::Value *result;
+ bool shouldRetain = shouldRetainObjCLifetime(type.getObjCLifetime());
+ if (shouldRetain) {
+ result = CGF.EmitLoadOfLValue(lvalue, SourceLocation()).getScalarVal();
+ } else {
+ assert(type.getObjCLifetime() == Qualifiers::OCL_Weak);
+ result = CGF.EmitARCLoadWeakRetained(lvalue.getAddress());
+ }
+ return TryEmitResult(result, !shouldRetain);
+}
+
static TryEmitResult tryEmitARCRetainLoadOfScalar(CodeGenFunction &CGF,
const Expr *e) {
e = e->IgnoreParens();
@@ -2500,6 +2509,17 @@
cast<BinaryOperator>(e)->getOpcode() == BO_Assign)
return TryEmitResult(CGF.EmitScalarExpr(e), false);
+ // TODO: update comment when settled on implementation.
+ // DeclRefExpr referencing non-odr-used variable might be constant-evaluated
+ // and in this case we don't have l-value. Emit code for scalar expression
+ // instead of emitting LValue and loading it.
+ if (const auto *decl_expr = dyn_cast<DeclRefExpr>(e)) {
+ auto *DRE = const_cast<DeclRefExpr *>(decl_expr);
+ if (CodeGenFunction::ConstantEmission constant = CGF.tryEmitAsConstant(DRE))
+ return TryEmitResult(CGF.emitScalarConstant(constant, DRE),
+ !shouldRetainObjCLifetime(type.getObjCLifetime()));
+ }
+
return tryEmitARCRetainLoadOfScalar(CGF, CGF.EmitLValue(e), type);
}
Index: clang/lib/CodeGen/CGExprScalar.cpp
===================================================================
--- clang/lib/CodeGen/CGExprScalar.cpp
+++ clang/lib/CodeGen/CGExprScalar.cpp
@@ -456,19 +456,10 @@
return CGF.getOrCreateOpaqueRValueMapping(E).getScalarVal();
}
- Value *emitConstant(const CodeGenFunction::ConstantEmission &Constant,
- Expr *E) {
- assert(Constant && "not a constant");
- if (Constant.isReference())
- return EmitLoadOfLValue(Constant.getReferenceLValue(CGF, E),
- E->getExprLoc());
- return Constant.getValue();
- }
-
// l-values.
Value *VisitDeclRefExpr(DeclRefExpr *E) {
if (CodeGenFunction::ConstantEmission Constant = CGF.tryEmitAsConstant(E))
- return emitConstant(Constant, E);
+ return CGF.emitScalarConstant(Constant, E);
return EmitLoadOfLValue(E);
}
@@ -1545,7 +1536,7 @@
Value *ScalarExprEmitter::VisitMemberExpr(MemberExpr *E) {
if (CodeGenFunction::ConstantEmission Constant = CGF.tryEmitAsConstant(E)) {
CGF.EmitIgnoredExpr(E->getBase());
- return emitConstant(Constant, E);
+ return CGF.emitScalarConstant(Constant, E);
} else {
llvm::APSInt Value;
if (E->EvaluateAsInt(Value, CGF.getContext(), Expr::SE_AllowSideEffects)) {
Index: clang/lib/CodeGen/CGExpr.cpp
===================================================================
--- clang/lib/CodeGen/CGExpr.cpp
+++ clang/lib/CodeGen/CGExpr.cpp
@@ -1491,6 +1491,16 @@
return ConstantEmission();
}
+llvm::Value *CodeGenFunction::emitScalarConstant(
+ const CodeGenFunction::ConstantEmission &Constant, Expr *E) {
+ assert(Constant && "not a constant");
+ if (Constant.isReference())
+ return EmitLoadOfLValue(Constant.getReferenceLValue(*this, E),
+ E->getExprLoc())
+ .getScalarVal();
+ return Constant.getValue();
+}
+
llvm::Value *CodeGenFunction::EmitLoadOfScalar(LValue lvalue,
SourceLocation Loc) {
return EmitLoadOfScalar(lvalue.getAddress(), lvalue.isVolatile(),
[Attachment #4 (text/plain)]
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic