llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Timm Baeder (tbaederr) <details> <summary>Changes</summary> It isn't always the same as 'value == 0'. --- Full diff: https://github.com/llvm/llvm-project/pull/202356.diff 6 Files Affected: - (modified) clang/lib/AST/ByteCode/Compiler.cpp (+30-2) - (modified) clang/lib/AST/ByteCode/Interp.h (+21-6) - (modified) clang/lib/AST/ByteCode/Opcodes.td (+5-1) - (modified) clang/lib/AST/ByteCode/Pointer.cpp (+7-3) - (modified) clang/lib/AST/ByteCode/Pointer.h (+7-4) - (added) clang/test/AST/ByteCode/codegen.cl (+17) ``````````diff diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp index 76688e30a0acd..f35c745defab2 100644 --- a/clang/lib/AST/ByteCode/Compiler.cpp +++ b/clang/lib/AST/ByteCode/Compiler.cpp @@ -491,7 +491,8 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *E) { Desc = P.createDescriptor(E, PtrType->getPointeeType().getTypePtr(), Descriptor::InlineDescMD, /*IsConst=*/true); - if (!this->emitGetIntPtr(T, Desc, E)) + uint64_t Val = Ctx.getASTContext().getTargetNullPointerValue(E->getType()); + if (!this->emitGetIntPtr(T, Desc, Val, E)) return false; PrimType DestPtrT = classifyPrim(PtrType); @@ -508,10 +509,37 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *E) { case CK_NonAtomicToAtomic: case CK_NoOp: case CK_UserDefinedConversion: - case CK_AddressSpaceConversion: case CK_CPointerToObjCPointerCast: return this->delegate(SubExpr); + case CK_AddressSpaceConversion: { + if (E->containsErrors()) + return false; + + if (!this->visit(SubExpr)) + return false; + + const Descriptor *Desc = nullptr; + const QualType PointeeType = E->getType()->getPointeeType(); + uint64_t Val; + if (!PointeeType.isNull()) { + Val = Ctx.getASTContext().getTargetNullPointerValue(E->getType()); + if (OptPrimType T = classify(PointeeType)) + Desc = P.createDescriptor(SubExpr, *T); + else + Desc = P.createDescriptor(SubExpr, PointeeType.getTypePtr(), + std::nullopt, /*IsConst=*/true); + } else { + Val = 0; + } + + if (!this->emitCastAddressSpace(Val, Desc, E)) + return false; + if (DiscardResult) + return this->emitPopPtr(E); + return true; + } + case CK_BitCast: { if (E->containsErrors()) return false; diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h index d2ca122d0e805..a9b4b5f8ddfa8 100644 --- a/clang/lib/AST/ByteCode/Interp.h +++ b/clang/lib/AST/ByteCode/Interp.h @@ -3099,7 +3099,20 @@ 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); + if constexpr (std::is_same_v<T, Pointer>) + S.Stk.push<T>(Value, Desc, 0, true); + else + S.Stk.push<T>(Value, Desc); + return true; +} + +inline bool CastAddressSpace(InterpState &S, CodePtr OpPC, uint64_t Value, + const Descriptor *Desc) { + const Pointer Ptr = S.Stk.pop<Pointer>(); + if (Ptr.isZero()) + S.Stk.push<Pointer>(Value, Desc); + else + S.Stk.push<Pointer>(Ptr); return true; } @@ -3539,7 +3552,8 @@ inline bool GetFnPtr(InterpState &S, CodePtr OpPC, const Function *Func) { } template <PrimType Name, class T = typename PrimConv<Name>::T> -inline bool GetIntPtr(InterpState &S, CodePtr OpPC, const Descriptor *Desc) { +inline bool GetIntPtr(InterpState &S, CodePtr OpPC, const Descriptor *Desc, + uint64_t NullValue) { const T &IntVal = S.Stk.pop<T>(); S.CCEDiag(S.Current->getSource(OpPC), diag::note_constexpr_invalid_cast) @@ -3564,7 +3578,8 @@ inline bool GetIntPtr(InterpState &S, CodePtr OpPC, const Descriptor *Desc) { S.P.getFunction((const FunctionDecl *)IntVal.getPtr()); S.Stk.push<Pointer>(F, IntVal.getOffset()); } else { - S.Stk.push<Pointer>(static_cast<uint64_t>(IntVal), Desc); + S.Stk.push<Pointer>(static_cast<uint64_t>(IntVal), Desc, 0, + static_cast<uint64_t>(IntVal) == NullValue); } } else { S.Stk.push<Pointer>(static_cast<uint64_t>(IntVal), Desc); @@ -3848,7 +3863,7 @@ inline bool AllocN(InterpState &S, CodePtr OpPC, PrimType T, const Expr *Source, return false; // If this failed and is nothrow, just return a null ptr. - S.Stk.push<Pointer>(0, nullptr); + S.Stk.push<Pointer>(); return true; } if (NumElements.isNegative()) { @@ -3857,7 +3872,7 @@ inline bool AllocN(InterpState &S, CodePtr OpPC, PrimType T, const Expr *Source, << NumElements.toDiagnosticString(S.getASTContext()); return false; } - S.Stk.push<Pointer>(0, nullptr); + S.Stk.push<Pointer>(); return true; } @@ -3891,7 +3906,7 @@ inline bool AllocCN(InterpState &S, CodePtr OpPC, const Descriptor *ElementDesc, return false; // If this failed and is nothrow, just return a null ptr. - S.Stk.push<Pointer>(0, ElementDesc); + S.Stk.push<Pointer>(0, ElementDesc, 0, /*IsNull=*/true); return true; } if (NumElements.isNegative()) { diff --git a/clang/lib/AST/ByteCode/Opcodes.td b/clang/lib/AST/ByteCode/Opcodes.td index 4bd61cdce658d..035e16a161a4d 100644 --- a/clang/lib/AST/ByteCode/Opcodes.td +++ b/clang/lib/AST/ByteCode/Opcodes.td @@ -315,6 +315,10 @@ def Null : Opcode { let HasGroup = 1; } +def CastAddressSpace : Opcode { + let Args = [ArgUint64, ArgDesc]; +} + //===----------------------------------------------------------------------===// // Pointer generation //===----------------------------------------------------------------------===// @@ -596,7 +600,7 @@ def GetFnPtr : Opcode { def GetIntPtr : Opcode { let Types = [AluTypeClass]; - let Args = [ArgDesc]; + let Args = [ArgDesc, ArgUint64]; let HasGroup = 1; } diff --git a/clang/lib/AST/ByteCode/Pointer.cpp b/clang/lib/AST/ByteCode/Pointer.cpp index 96409faeb6929..b27c17747e778 100644 --- a/clang/lib/AST/ByteCode/Pointer.cpp +++ b/clang/lib/AST/ByteCode/Pointer.cpp @@ -338,7 +338,8 @@ void Pointer::print(llvm::raw_ostream &OS) const { } break; case Storage::Int: OS << "(Int) {"; - OS << Int.Value << " + " << Offset << ", " << Int.Desc; + OS << Int.Value << " + " << Offset << ", " << Int.Desc << ", " + << (Int.IsNull ? "null" : "nonnull"); OS << "}"; break; case Storage::Fn: @@ -1021,7 +1022,9 @@ std::optional<IntPointer> IntPointer::atOffset(const ASTContext &ASTCtx, uint64_t FieldOffset = ASTCtx.toCharUnitsFromBits(Layout.getFieldOffset(FieldIndex)) .getQuantity(); - return IntPointer{F->Desc, this->Value + FieldOffset}; + + uint64_t NewValue = this->Value + FieldOffset; + return IntPointer{F->Desc, NewValue, NewValue == 0}; } IntPointer IntPointer::baseCast(const ASTContext &ASTCtx, @@ -1048,5 +1051,6 @@ IntPointer IntPointer::baseCast(const ASTContext &ASTCtx, CharUnits BaseLayoutOffset = Layout.getBaseClassOffset(cast<CXXRecordDecl>(BaseDesc->asDecl())); - return {BaseDesc, Value + BaseLayoutOffset.getQuantity()}; + uint64_t NewValue = Value + BaseLayoutOffset.getQuantity(); + return {BaseDesc, NewValue, NewValue == 0}; } diff --git a/clang/lib/AST/ByteCode/Pointer.h b/clang/lib/AST/ByteCode/Pointer.h index a77918f667fd3..96cb667f02c3a 100644 --- a/clang/lib/AST/ByteCode/Pointer.h +++ b/clang/lib/AST/ByteCode/Pointer.h @@ -47,6 +47,7 @@ struct BlockPointer { struct IntPointer { const Descriptor *Desc; uint64_t Value; + bool IsNull = false; std::optional<IntPointer> atOffset(const ASTContext &ASTCtx, unsigned Offset) const; @@ -100,15 +101,17 @@ class Pointer { static constexpr unsigned RootPtrMark = ~0u; public: - Pointer() : StorageKind(Storage::Int), Int{nullptr, 0} {} + Pointer() : StorageKind(Storage::Int), Int{nullptr, 0, true} {} Pointer(IntPointer &&IntPtr) : StorageKind(Storage::Int), Int(std::move(IntPtr)) {} Pointer(Block *B); Pointer(Block *B, uint64_t BaseAndOffset); Pointer(const Pointer &P); Pointer(Pointer &&P); - Pointer(uint64_t Address, const Descriptor *Desc, uint64_t Offset = 0) - : Offset(Offset), StorageKind(Storage::Int), Int{Desc, Address} {} + Pointer(uint64_t Address, const Descriptor *Desc, uint64_t Offset = 0, + std::optional<bool> IsNull = std::nullopt) + : Offset(Offset), StorageKind(Storage::Int), + Int{Desc, Address, IsNull.value_or(Address == 0)} {} Pointer(const Function *F, uint64_t Offset = 0) : Offset(Offset), StorageKind(Storage::Fn), Fn{F} {} Pointer(const Type *TypePtr, const Type *TypeInfoType, uint64_t Offset = 0) @@ -264,7 +267,7 @@ class Pointer { bool isZero() const { switch (StorageKind) { case Storage::Int: - return Int.Value == 0 && Offset == 0; + return Int.IsNull; case Storage::Block: return BS.Pointee == nullptr; case Storage::Fn: diff --git a/clang/test/AST/ByteCode/codegen.cl b/clang/test/AST/ByteCode/codegen.cl new file mode 100644 index 0000000000000..d2e331905e02d --- /dev/null +++ b/clang/test/AST/ByteCode/codegen.cl @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -no-enable-noundef-analysis %s -cl-std=CL2.0 -triple amdgcn -fcommon -O0 -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -no-enable-noundef-analysis %s -cl-std=CL2.0 -triple amdgcn -fcommon -O0 -emit-llvm -o - -fexperimental-new-constant-interpreter | FileCheck %s + +// CHECK: @fold_int_local ={{.*}} addrspace(1) global i32 13, align 4 +int fold_int_local = (int)(local void*)(generic char*)(global int*)0 + 14; + +// CHECK: @fold_int ={{.*}} addrspace(1) global i32 13, align 4 +int fold_int = (int)(private void*)(generic char*)(global int*)0 + 14; + +// CHECK: @test_static_var_private.sp4 = internal addrspace(1) global ptr addrspace(5) null, align 4 +// CHECK: @test_static_var_private.sp5 = internal addrspace(1) global ptr addrspace(5) addrspacecast (ptr null to ptr addrspace(5)), align 4 + +void test_static_var_private(void) { + static private char *sp4 = (private char*)((void)0, 0); + const int x = 0; + static private char *sp5 = (private char*)x; +} `````````` </details> https://github.com/llvm/llvm-project/pull/202356 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
