-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[clang][bytecode] Not all null pointers are 0 #118601
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 Author: Timm Baeder (tbaederr) ChangesGet the Value from the ASTContext insteaed. Full diff: https://github.com/llvm/llvm-project/pull/118601.diff 4 Files Affected:
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index a95353fd2943c9..b395aedc378050 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -355,7 +355,9 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
std::nullopt, true, false,
/*IsMutable=*/false, nullptr);
}
- return this->emitNull(classifyPrim(CE->getType()), Desc, CE);
+
+ uint64_t Val = Ctx.getASTContext().getTargetNullPointerValue(CE->getType());
+ return this->emitNull(classifyPrim(CE->getType()), Val, Desc, CE);
}
case CK_PointerToIntegral: {
@@ -3814,7 +3816,7 @@ template <class Emitter> bool Compiler<Emitter>::visitBool(const Expr *E) {
// Convert pointers to bool.
if (T == PT_Ptr || T == PT_FnPtr) {
- if (!this->emitNull(*T, nullptr, E))
+ if (!this->emitNull(*T, 0, nullptr, E))
return false;
return this->emitNE(*T, E);
}
@@ -3854,11 +3856,12 @@ bool Compiler<Emitter>::visitZeroInitializer(PrimType T, QualType QT,
case PT_IntAPS:
return this->emitZeroIntAPS(Ctx.getBitWidth(QT), E);
case PT_Ptr:
- return this->emitNullPtr(nullptr, E);
+ return this->emitNullPtr(Ctx.getASTContext().getTargetNullPointerValue(QT),
+ nullptr, E);
case PT_FnPtr:
- return this->emitNullFnPtr(nullptr, E);
+ return this->emitNullFnPtr(0, nullptr, E);
case PT_MemberPtr:
- return this->emitNullMemberPtr(nullptr, E);
+ return this->emitNullMemberPtr(0, nullptr, E);
case PT_Float:
return this->emitConstFloat(APFloat::getZero(Ctx.getFloatSemantics(QT)), E);
case PT_FixedPoint: {
@@ -4418,7 +4421,7 @@ bool Compiler<Emitter>::visitAPValue(const APValue &Val, PrimType ValType,
if (Val.isLValue()) {
if (Val.isNullPointer())
- return this->emitNull(ValType, nullptr, E);
+ return this->emitNull(ValType, 0, nullptr, E);
APValue::LValueBase Base = Val.getLValueBase();
if (const Expr *BaseExpr = Base.dyn_cast<const Expr *>())
return this->visit(BaseExpr);
@@ -4428,7 +4431,7 @@ bool Compiler<Emitter>::visitAPValue(const APValue &Val, PrimType ValType,
} else if (Val.isMemberPointer()) {
if (const ValueDecl *MemberDecl = Val.getMemberPointerDecl())
return this->emitGetMemberPtr(MemberDecl, E);
- return this->emitNullMemberPtr(nullptr, E);
+ return this->emitNullMemberPtr(0, nullptr, E);
}
return false;
@@ -4780,7 +4783,8 @@ bool Compiler<Emitter>::VisitCXXNullPtrLiteralExpr(
if (DiscardResult)
return true;
- return this->emitNullPtr(nullptr, E);
+ uint64_t Val = Ctx.getASTContext().getTargetNullPointerValue(E->getType());
+ return this->emitNullPtr(Val, nullptr, E);
}
template <class Emitter>
@@ -5330,7 +5334,7 @@ bool Compiler<Emitter>::emitLambdaStaticInvokerBody(const CXXMethodDecl *MD) {
// one here, and we don't need one either because the lambda cannot have
// any captures, as verified above. Emit a null pointer. This is then
// special-cased when interpreting to not emit any misleading diagnostics.
- if (!this->emitNullPtr(nullptr, MD))
+ if (!this->emitNullPtr(0, nullptr, MD))
return false;
// Forward all arguments from the static invoker to the lambda call operator.
@@ -6477,7 +6481,7 @@ bool Compiler<Emitter>::emitBuiltinBitCast(const CastExpr *E) {
if (!this->discard(SubExpr))
return false;
- return this->emitNullPtr(nullptr, E);
+ return this->emitNullPtr(0, nullptr, E);
}
if (FromType->isNullPtrType() && ToT) {
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index 25740c90d240ab..c5c2a5ef19cc4d 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -2432,9 +2432,11 @@ static inline bool ZeroIntAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
}
template <PrimType Name, class T = typename PrimConv<Name>::T>
-inline bool Null(InterpState &S, CodePtr OpPC, const Descriptor *Desc) {
- // Note: Desc can be null.
- S.Stk.push<T>(0, Desc);
+inline bool Null(InterpState &S, CodePtr OpPC, uint64_t Value,
+ const Descriptor *Desc) {
+ // FIXME(perf): This is a somewhat often-used function and the value of a
+ // null pointer is almost always 0.
+ S.Stk.push<T>(Value, Desc);
return true;
}
diff --git a/clang/lib/AST/ByteCode/Opcodes.td b/clang/lib/AST/ByteCode/Opcodes.td
index 26d5f70b44396b..0638f8249805f8 100644
--- a/clang/lib/AST/ByteCode/Opcodes.td
+++ b/clang/lib/AST/ByteCode/Opcodes.td
@@ -281,7 +281,7 @@ def ZeroIntAPS : Opcode {
// [] -> [Pointer]
def Null : Opcode {
let Types = [PtrTypeClass];
- let Args = [ArgDesc];
+ let Args = [ArgUint64, ArgDesc];
let HasGroup = 1;
}
diff --git a/clang/test/AST/ByteCode/amdgpu-nullptr.cl b/clang/test/AST/ByteCode/amdgpu-nullptr.cl
new file mode 100644
index 00000000000000..5f3af3cfdcaed5
--- /dev/null
+++ b/clang/test/AST/ByteCode/amdgpu-nullptr.cl
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -no-enable-noundef-analysis %s -cl-std=CL2.0 -include opencl-c.h -triple amdgcn -emit-llvm -o - | FileCheck %s
+
+// RUN: %clang_cc1 -no-enable-noundef-analysis %s -cl-std=CL2.0 -include opencl-c.h -triple amdgcn -emit-llvm -fexperimental-new-constant-interpreter -o - | FileCheck %s
+
+
+// CHECK: @fold_priv ={{.*}} local_unnamed_addr addrspace(1) global ptr addrspace(5) addrspacecast (ptr addrspace(1) null to ptr addrspace(5)), align 4
+private short *fold_priv = (private short*)(generic int*)(global void*)0;
+
+// CHECK: @fold_priv_arith ={{.*}} local_unnamed_addr addrspace(1) global ptr addrspace(5) inttoptr (i32 9 to ptr addrspace(5)), align 4
+private char *fold_priv_arith = (private char*)0 + 10;
+
+
|
@llvm/pr-subscribers-backend-amdgpu Author: Timm Baeder (tbaederr) ChangesGet the Value from the ASTContext insteaed. Full diff: https://github.com/llvm/llvm-project/pull/118601.diff 4 Files Affected:
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index a95353fd2943c9..b395aedc378050 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -355,7 +355,9 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
std::nullopt, true, false,
/*IsMutable=*/false, nullptr);
}
- return this->emitNull(classifyPrim(CE->getType()), Desc, CE);
+
+ uint64_t Val = Ctx.getASTContext().getTargetNullPointerValue(CE->getType());
+ return this->emitNull(classifyPrim(CE->getType()), Val, Desc, CE);
}
case CK_PointerToIntegral: {
@@ -3814,7 +3816,7 @@ template <class Emitter> bool Compiler<Emitter>::visitBool(const Expr *E) {
// Convert pointers to bool.
if (T == PT_Ptr || T == PT_FnPtr) {
- if (!this->emitNull(*T, nullptr, E))
+ if (!this->emitNull(*T, 0, nullptr, E))
return false;
return this->emitNE(*T, E);
}
@@ -3854,11 +3856,12 @@ bool Compiler<Emitter>::visitZeroInitializer(PrimType T, QualType QT,
case PT_IntAPS:
return this->emitZeroIntAPS(Ctx.getBitWidth(QT), E);
case PT_Ptr:
- return this->emitNullPtr(nullptr, E);
+ return this->emitNullPtr(Ctx.getASTContext().getTargetNullPointerValue(QT),
+ nullptr, E);
case PT_FnPtr:
- return this->emitNullFnPtr(nullptr, E);
+ return this->emitNullFnPtr(0, nullptr, E);
case PT_MemberPtr:
- return this->emitNullMemberPtr(nullptr, E);
+ return this->emitNullMemberPtr(0, nullptr, E);
case PT_Float:
return this->emitConstFloat(APFloat::getZero(Ctx.getFloatSemantics(QT)), E);
case PT_FixedPoint: {
@@ -4418,7 +4421,7 @@ bool Compiler<Emitter>::visitAPValue(const APValue &Val, PrimType ValType,
if (Val.isLValue()) {
if (Val.isNullPointer())
- return this->emitNull(ValType, nullptr, E);
+ return this->emitNull(ValType, 0, nullptr, E);
APValue::LValueBase Base = Val.getLValueBase();
if (const Expr *BaseExpr = Base.dyn_cast<const Expr *>())
return this->visit(BaseExpr);
@@ -4428,7 +4431,7 @@ bool Compiler<Emitter>::visitAPValue(const APValue &Val, PrimType ValType,
} else if (Val.isMemberPointer()) {
if (const ValueDecl *MemberDecl = Val.getMemberPointerDecl())
return this->emitGetMemberPtr(MemberDecl, E);
- return this->emitNullMemberPtr(nullptr, E);
+ return this->emitNullMemberPtr(0, nullptr, E);
}
return false;
@@ -4780,7 +4783,8 @@ bool Compiler<Emitter>::VisitCXXNullPtrLiteralExpr(
if (DiscardResult)
return true;
- return this->emitNullPtr(nullptr, E);
+ uint64_t Val = Ctx.getASTContext().getTargetNullPointerValue(E->getType());
+ return this->emitNullPtr(Val, nullptr, E);
}
template <class Emitter>
@@ -5330,7 +5334,7 @@ bool Compiler<Emitter>::emitLambdaStaticInvokerBody(const CXXMethodDecl *MD) {
// one here, and we don't need one either because the lambda cannot have
// any captures, as verified above. Emit a null pointer. This is then
// special-cased when interpreting to not emit any misleading diagnostics.
- if (!this->emitNullPtr(nullptr, MD))
+ if (!this->emitNullPtr(0, nullptr, MD))
return false;
// Forward all arguments from the static invoker to the lambda call operator.
@@ -6477,7 +6481,7 @@ bool Compiler<Emitter>::emitBuiltinBitCast(const CastExpr *E) {
if (!this->discard(SubExpr))
return false;
- return this->emitNullPtr(nullptr, E);
+ return this->emitNullPtr(0, nullptr, E);
}
if (FromType->isNullPtrType() && ToT) {
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index 25740c90d240ab..c5c2a5ef19cc4d 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -2432,9 +2432,11 @@ static inline bool ZeroIntAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
}
template <PrimType Name, class T = typename PrimConv<Name>::T>
-inline bool Null(InterpState &S, CodePtr OpPC, const Descriptor *Desc) {
- // Note: Desc can be null.
- S.Stk.push<T>(0, Desc);
+inline bool Null(InterpState &S, CodePtr OpPC, uint64_t Value,
+ const Descriptor *Desc) {
+ // FIXME(perf): This is a somewhat often-used function and the value of a
+ // null pointer is almost always 0.
+ S.Stk.push<T>(Value, Desc);
return true;
}
diff --git a/clang/lib/AST/ByteCode/Opcodes.td b/clang/lib/AST/ByteCode/Opcodes.td
index 26d5f70b44396b..0638f8249805f8 100644
--- a/clang/lib/AST/ByteCode/Opcodes.td
+++ b/clang/lib/AST/ByteCode/Opcodes.td
@@ -281,7 +281,7 @@ def ZeroIntAPS : Opcode {
// [] -> [Pointer]
def Null : Opcode {
let Types = [PtrTypeClass];
- let Args = [ArgDesc];
+ let Args = [ArgUint64, ArgDesc];
let HasGroup = 1;
}
diff --git a/clang/test/AST/ByteCode/amdgpu-nullptr.cl b/clang/test/AST/ByteCode/amdgpu-nullptr.cl
new file mode 100644
index 00000000000000..5f3af3cfdcaed5
--- /dev/null
+++ b/clang/test/AST/ByteCode/amdgpu-nullptr.cl
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -no-enable-noundef-analysis %s -cl-std=CL2.0 -include opencl-c.h -triple amdgcn -emit-llvm -o - | FileCheck %s
+
+// RUN: %clang_cc1 -no-enable-noundef-analysis %s -cl-std=CL2.0 -include opencl-c.h -triple amdgcn -emit-llvm -fexperimental-new-constant-interpreter -o - | FileCheck %s
+
+
+// CHECK: @fold_priv ={{.*}} local_unnamed_addr addrspace(1) global ptr addrspace(5) addrspacecast (ptr addrspace(1) null to ptr addrspace(5)), align 4
+private short *fold_priv = (private short*)(generic int*)(global void*)0;
+
+// CHECK: @fold_priv_arith ={{.*}} local_unnamed_addr addrspace(1) global ptr addrspace(5) inttoptr (i32 9 to ptr addrspace(5)), align 4
+private char *fold_priv_arith = (private char*)0 + 10;
+
+
|
@@ -0,0 +1,12 @@ | |||
// RUN: %clang_cc1 -no-enable-noundef-analysis %s -cl-std=CL2.0 -include opencl-c.h -triple amdgcn -emit-llvm -o - | FileCheck %s |
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.
I don't think you need the -include opencl-c.h
for this test? (it's rather big, so slows down testing)
Same comment applies to the next RUN line.
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.
Ah, nice. Thanks
Get the Value from the ASTContext insteaed.
12e94b9
to
a929550
Compare
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.
LGTM, but I'm not an expert in this area so I'll leave the formal approval to someone else.
Get the Value from the ASTContext instead.