Author: nico Date: Wed Dec 14 15:38:18 2016 New Revision: 289713 URL: http://llvm.org/viewvc/llvm-project?rev=289713&view=rev Log: Revert 289252 (and follow-up 289285), it caused PR31374
Removed: cfe/trunk/test/CodeGenOpenCL/amdgpu-nullptr.cl Modified: cfe/trunk/include/clang/AST/APValue.h cfe/trunk/include/clang/AST/ASTContext.h cfe/trunk/include/clang/Basic/TargetInfo.h cfe/trunk/lib/AST/APValue.cpp cfe/trunk/lib/AST/ASTContext.cpp cfe/trunk/lib/AST/ExprConstant.cpp cfe/trunk/lib/Basic/Targets.cpp cfe/trunk/lib/CodeGen/CGDecl.cpp cfe/trunk/lib/CodeGen/CGExprAgg.cpp cfe/trunk/lib/CodeGen/CGExprConstant.cpp cfe/trunk/lib/CodeGen/CGExprScalar.cpp cfe/trunk/lib/CodeGen/CodeGenModule.cpp cfe/trunk/lib/CodeGen/CodeGenModule.h cfe/trunk/lib/CodeGen/CodeGenTypes.cpp cfe/trunk/lib/CodeGen/CodeGenTypes.h cfe/trunk/lib/CodeGen/TargetInfo.cpp cfe/trunk/lib/CodeGen/TargetInfo.h Modified: cfe/trunk/include/clang/AST/APValue.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/APValue.h?rev=289713&r1=289712&r2=289713&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/APValue.h (original) +++ cfe/trunk/include/clang/AST/APValue.h Wed Dec 14 15:38:18 2016 @@ -135,15 +135,14 @@ public: } APValue(const APValue &RHS); APValue(APValue &&RHS) : Kind(Uninitialized) { swap(RHS); } - APValue(LValueBase B, const CharUnits &O, NoLValuePath N, unsigned CallIndex, - bool IsNullPtr = false) + APValue(LValueBase B, const CharUnits &O, NoLValuePath N, unsigned CallIndex) : Kind(Uninitialized) { - MakeLValue(); setLValue(B, O, N, CallIndex, IsNullPtr); + MakeLValue(); setLValue(B, O, N, CallIndex); } APValue(LValueBase B, const CharUnits &O, ArrayRef<LValuePathEntry> Path, - bool OnePastTheEnd, unsigned CallIndex, bool IsNullPtr = false) + bool OnePastTheEnd, unsigned CallIndex) : Kind(Uninitialized) { - MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, CallIndex, IsNullPtr); + MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, CallIndex); } APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(Uninitialized) { MakeArray(InitElts, Size); @@ -255,7 +254,6 @@ public: bool hasLValuePath() const; ArrayRef<LValuePathEntry> getLValuePath() const; unsigned getLValueCallIndex() const; - bool isNullPointer() const; APValue &getVectorElt(unsigned I) { assert(isVector() && "Invalid accessor"); @@ -376,10 +374,10 @@ public: ((ComplexAPFloat *)(char *)Data.buffer)->Imag = std::move(I); } void setLValue(LValueBase B, const CharUnits &O, NoLValuePath, - unsigned CallIndex, bool IsNullPtr); + unsigned CallIndex); void setLValue(LValueBase B, const CharUnits &O, ArrayRef<LValuePathEntry> Path, bool OnePastTheEnd, - unsigned CallIndex, bool IsNullPtr); + unsigned CallIndex); void setUnion(const FieldDecl *Field, const APValue &Value) { assert(isUnion() && "Invalid accessor"); ((UnionData*)(char*)Data.buffer)->Field = Field; Modified: cfe/trunk/include/clang/AST/ASTContext.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=289713&r1=289712&r2=289713&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/ASTContext.h (original) +++ cfe/trunk/include/clang/AST/ASTContext.h Wed Dec 14 15:38:18 2016 @@ -2295,10 +2295,6 @@ public: return (*AddrSpaceMap)[AS - LangAS::Offset]; } - /// Get target-dependent integer value for null pointer which is used for - /// constant folding. - uint64_t getTargetNullPointerValue(QualType QT) const; - bool addressSpaceMapManglingFor(unsigned AS) const { return AddrSpaceMapMangling || AS < LangAS::Offset || Modified: cfe/trunk/include/clang/Basic/TargetInfo.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TargetInfo.h?rev=289713&r1=289712&r2=289713&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/TargetInfo.h (original) +++ cfe/trunk/include/clang/Basic/TargetInfo.h Wed Dec 14 15:38:18 2016 @@ -42,7 +42,6 @@ class DiagnosticsEngine; class LangOptions; class CodeGenOptions; class MacroBuilder; -class QualType; class SourceLocation; class SourceManager; @@ -301,12 +300,6 @@ public: return PointerWidth; } - /// \brief Get integer value for null pointer. - /// \param AddrSpace address space of pointee in source language. - virtual uint64_t getNullPointerValue(unsigned AddrSpace) const { - return 0; - } - /// \brief Return the size of '_Bool' and C++ 'bool' for this target, in bits. unsigned getBoolWidth() const { return BoolWidth; } Modified: cfe/trunk/lib/AST/APValue.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/APValue.cpp?rev=289713&r1=289712&r2=289713&view=diff ============================================================================== --- cfe/trunk/lib/AST/APValue.cpp (original) +++ cfe/trunk/lib/AST/APValue.cpp Wed Dec 14 15:38:18 2016 @@ -27,7 +27,6 @@ namespace { CharUnits Offset; unsigned PathLength; unsigned CallIndex; - bool IsNullPtr; }; } @@ -150,11 +149,10 @@ APValue::APValue(const APValue &RHS) : K MakeLValue(); if (RHS.hasLValuePath()) setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), RHS.getLValuePath(), - RHS.isLValueOnePastTheEnd(), RHS.getLValueCallIndex(), - RHS.isNullPointer()); + RHS.isLValueOnePastTheEnd(), RHS.getLValueCallIndex()); else setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), NoLValuePath(), - RHS.getLValueCallIndex(), RHS.isNullPointer()); + RHS.getLValueCallIndex()); break; case Array: MakeArray(RHS.getArrayInitializedElts(), RHS.getArraySize()); @@ -581,13 +579,8 @@ unsigned APValue::getLValueCallIndex() c return ((const LV*)(const char*)Data.buffer)->CallIndex; } -bool APValue::isNullPointer() const { - assert(isLValue() && "Invalid usage"); - return ((const LV*)(const char*)Data.buffer)->IsNullPtr; -} - void APValue::setLValue(LValueBase B, const CharUnits &O, NoLValuePath, - unsigned CallIndex, bool IsNullPtr) { + unsigned CallIndex) { assert(isLValue() && "Invalid accessor"); LV &LVal = *((LV*)(char*)Data.buffer); LVal.BaseAndIsOnePastTheEnd.setPointer(B); @@ -595,12 +588,11 @@ void APValue::setLValue(LValueBase B, co LVal.Offset = O; LVal.CallIndex = CallIndex; LVal.resizePath((unsigned)-1); - LVal.IsNullPtr = IsNullPtr; } void APValue::setLValue(LValueBase B, const CharUnits &O, ArrayRef<LValuePathEntry> Path, bool IsOnePastTheEnd, - unsigned CallIndex, bool IsNullPtr) { + unsigned CallIndex) { assert(isLValue() && "Invalid accessor"); LV &LVal = *((LV*)(char*)Data.buffer); LVal.BaseAndIsOnePastTheEnd.setPointer(B); @@ -609,7 +601,6 @@ void APValue::setLValue(LValueBase B, co LVal.CallIndex = CallIndex; LVal.resizePath(Path.size()); memcpy(LVal.getPath(), Path.data(), Path.size() * sizeof(LValuePathEntry)); - LVal.IsNullPtr = IsNullPtr; } const ValueDecl *APValue::getMemberPointerDecl() const { Modified: cfe/trunk/lib/AST/ASTContext.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=289713&r1=289712&r2=289713&view=diff ============================================================================== --- cfe/trunk/lib/AST/ASTContext.cpp (original) +++ cfe/trunk/lib/AST/ASTContext.cpp Wed Dec 14 15:38:18 2016 @@ -9426,16 +9426,6 @@ ASTContext::ObjCMethodsAreEqual(const Ob } -uint64_t ASTContext::getTargetNullPointerValue(QualType QT) const { - unsigned AS; - if (QT->getUnqualifiedDesugaredType()->isNullPtrType()) - AS = 0; - else - AS = QT->getPointeeType().getAddressSpace(); - - return getTargetInfo().getNullPointerValue(AS); -} - // Explicitly instantiate this in case a Redeclarable<T> is used from a TU that // doesn't include ASTContext.h template Modified: cfe/trunk/lib/AST/ExprConstant.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=289713&r1=289712&r2=289713&view=diff ============================================================================== --- cfe/trunk/lib/AST/ExprConstant.cpp (original) +++ cfe/trunk/lib/AST/ExprConstant.cpp Wed Dec 14 15:38:18 2016 @@ -1088,7 +1088,6 @@ namespace { unsigned InvalidBase : 1; unsigned CallIndex : 31; SubobjectDesignator Designator; - bool IsNullPtr; const APValue::LValueBase getLValueBase() const { return Base; } CharUnits &getLValueOffset() { return Offset; } @@ -1096,15 +1095,13 @@ namespace { unsigned getLValueCallIndex() const { return CallIndex; } SubobjectDesignator &getLValueDesignator() { return Designator; } const SubobjectDesignator &getLValueDesignator() const { return Designator;} - bool isNullPointer() const { return IsNullPtr;} void moveInto(APValue &V) const { if (Designator.Invalid) - V = APValue(Base, Offset, APValue::NoLValuePath(), CallIndex, - IsNullPtr); + V = APValue(Base, Offset, APValue::NoLValuePath(), CallIndex); else V = APValue(Base, Offset, Designator.Entries, - Designator.IsOnePastTheEnd, CallIndex, IsNullPtr); + Designator.IsOnePastTheEnd, CallIndex); } void setFrom(ASTContext &Ctx, const APValue &V) { assert(V.isLValue()); @@ -1113,17 +1110,14 @@ namespace { InvalidBase = false; CallIndex = V.getLValueCallIndex(); Designator = SubobjectDesignator(Ctx, V); - IsNullPtr = V.isNullPointer(); } - void set(APValue::LValueBase B, unsigned I = 0, bool BInvalid = false, - bool IsNullPtr_ = false, uint64_t Offset_ = 0) { + void set(APValue::LValueBase B, unsigned I = 0, bool BInvalid = false) { Base = B; - Offset = CharUnits::fromQuantity(Offset_); + Offset = CharUnits::Zero(); InvalidBase = BInvalid; CallIndex = I; Designator = SubobjectDesignator(getType(B)); - IsNullPtr = IsNullPtr_; } void setInvalid(APValue::LValueBase B, unsigned I = 0) { @@ -1136,7 +1130,7 @@ namespace { CheckSubobjectKind CSK) { if (Designator.Invalid) return false; - if (IsNullPtr) { + if (!Base) { Info.CCEDiag(E, diag::note_constexpr_null_subobject) << CSK; Designator.setInvalid(); @@ -1165,22 +1159,9 @@ namespace { if (checkSubobject(Info, E, Imag ? CSK_Imag : CSK_Real)) Designator.addComplexUnchecked(EltTy, Imag); } - void clearIsNullPointer() { - IsNullPtr = false; - } - void adjustOffsetAndIndex(EvalInfo &Info, const Expr *E, uint64_t Index, - CharUnits ElementSize) { - // Compute the new offset in the appropriate width. - Offset += Index * ElementSize; - if (Index && checkNullPointer(Info, E, CSK_ArrayIndex)) - Designator.adjustIndex(Info, E, Index); - if (Index) - clearIsNullPointer(); - } - void adjustOffset(CharUnits N) { - Offset += N; - if (N.getQuantity()) - clearIsNullPointer(); + void adjustIndex(EvalInfo &Info, const Expr *E, uint64_t N) { + if (N && checkNullPointer(Info, E, CSK_ArrayIndex)) + Designator.adjustIndex(Info, E, N); } }; @@ -2055,7 +2036,7 @@ static bool HandleLValueMember(EvalInfo } unsigned I = FD->getFieldIndex(); - LVal.adjustOffset(Info.Ctx.toCharUnitsFromBits(RL->getFieldOffset(I))); + LVal.Offset += Info.Ctx.toCharUnitsFromBits(RL->getFieldOffset(I)); LVal.addDecl(Info, E, FD); return true; } @@ -2109,7 +2090,9 @@ static bool HandleLValueArrayAdjustment( if (!HandleSizeof(Info, E->getExprLoc(), EltTy, SizeOfPointee)) return false; - LVal.adjustOffsetAndIndex(Info, E, Adjustment, SizeOfPointee); + // Compute the new offset in the appropriate width. + LVal.Offset += Adjustment * SizeOfPointee; + LVal.adjustIndex(Info, E, Adjustment); return true; } @@ -5095,9 +5078,7 @@ public: return true; } bool ZeroInitialization(const Expr *E) { - auto Offset = Info.Ctx.getTargetNullPointerValue(E->getType()); - Result.set((Expr*)nullptr, 0, false, true, Offset); - return true; + return Success((Expr*)nullptr); } bool VisitBinaryOperator(const BinaryOperator *E); @@ -5196,8 +5177,6 @@ bool PointerExprEvaluator::VisitCastExpr else CCEDiag(E, diag::note_constexpr_invalid_cast) << 2; } - if (E->getCastKind() == CK_AddressSpaceConversion && Result.IsNullPtr) - ZeroInitialization(E); return true; case CK_DerivedToBase: @@ -5239,7 +5218,6 @@ bool PointerExprEvaluator::VisitCastExpr Result.Offset = CharUnits::fromQuantity(N); Result.CallIndex = 0; Result.Designator.setInvalid(); - Result.IsNullPtr = false; return true; } else { // Cast is of an lvalue, no need to change value. @@ -8414,13 +8392,8 @@ bool IntExprEvaluator::VisitCastExpr(con return true; } - uint64_t V; - if (LV.isNullPointer()) - V = Info.Ctx.getTargetNullPointerValue(SrcType); - else - V = LV.getLValueOffset().getQuantity(); - - APSInt AsInt = Info.Ctx.MakeIntValue(V, SrcType); + APSInt AsInt = Info.Ctx.MakeIntValue(LV.getLValueOffset().getQuantity(), + SrcType); return Success(HandleIntToIntCast(Info, E, DestType, SrcType, AsInt), E); } Modified: cfe/trunk/lib/Basic/Targets.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Targets.cpp?rev=289713&r1=289712&r2=289713&view=diff ============================================================================== --- cfe/trunk/lib/Basic/Targets.cpp (original) +++ cfe/trunk/lib/Basic/Targets.cpp Wed Dec 14 15:38:18 2016 @@ -2245,13 +2245,6 @@ public: return CCCR_OK; } } - - // In amdgcn target the null pointer in global, constant, and generic - // address space has value 0 but in private and local address space has - // value ~0. - uint64_t getNullPointerValue(unsigned AS) const override { - return AS != LangAS::opencl_local && AS != 0 ? 0 : ~0; - } }; const Builtin::Info AMDGPUTargetInfo::BuiltinInfo[] = { Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=289713&r1=289712&r2=289713&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGDecl.cpp (original) +++ cfe/trunk/lib/CodeGen/CGDecl.cpp Wed Dec 14 15:38:18 2016 @@ -708,7 +708,7 @@ void CodeGenFunction::EmitScalarInit(con } auto ty = cast<llvm::PointerType>(tempLV.getAddress().getElementType()); - llvm::Value *zero = CGM.getNullPointer(ty, tempLV.getType()); + llvm::Value *zero = llvm::ConstantPointerNull::get(ty); // If __weak, we want to use a barrier under certain conditions. if (lifetime == Qualifiers::OCL_Weak) Modified: cfe/trunk/lib/CodeGen/CGExprAgg.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprAgg.cpp?rev=289713&r1=289712&r2=289713&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGExprAgg.cpp (original) +++ cfe/trunk/lib/CodeGen/CGExprAgg.cpp Wed Dec 14 15:38:18 2016 @@ -1052,8 +1052,7 @@ static bool isSimpleZero(const Expr *E, return true; // (int*)0 - Null pointer expressions. if (const CastExpr *ICE = dyn_cast<CastExpr>(E)) - return ICE->getCastKind() == CK_NullToPointer && - CGF.getTypes().isPointerZeroInitializable(E->getType()); + return ICE->getCastKind() == CK_NullToPointer; // '\0' if (const CharacterLiteral *CL = dyn_cast<CharacterLiteral>(E)) return CL->getValue() == 0; Modified: cfe/trunk/lib/CodeGen/CGExprConstant.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprConstant.cpp?rev=289713&r1=289712&r2=289713&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGExprConstant.cpp (original) +++ cfe/trunk/lib/CodeGen/CGExprConstant.cpp Wed Dec 14 15:38:18 2016 @@ -16,7 +16,6 @@ #include "CGObjCRuntime.h" #include "CGRecordLayout.h" #include "CodeGenModule.h" -#include "TargetInfo.h" #include "clang/AST/APValue.h" #include "clang/AST/ASTContext.h" #include "clang/AST/RecordLayout.h" @@ -1263,10 +1262,6 @@ llvm::Constant *CodeGenModule::EmitConst return C; } -llvm::Constant *CodeGenModule::getNullPointer(llvm::PointerType *T, QualType QT) { - return getTargetCodeGenInfo().getNullPointer(*this, T, QT); -} - llvm::Constant *CodeGenModule::EmitConstantValue(const APValue &Value, QualType DestType, CodeGenFunction *CGF) { @@ -1298,7 +1293,6 @@ llvm::Constant *CodeGenModule::EmitConst llvm::ConstantInt::get(Int64Ty, Value.getLValueOffset().getQuantity()); llvm::Constant *C = nullptr; - if (APValue::LValueBase LVBase = Value.getLValueBase()) { // An array can be represented as an lvalue referring to the base. if (isa<llvm::ArrayType>(DestTy)) { @@ -1329,9 +1323,7 @@ llvm::Constant *CodeGenModule::EmitConst // Convert to the appropriate type; this could be an lvalue for // an integer. - if (auto PT = dyn_cast<llvm::PointerType>(DestTy)) { - if (Value.isNullPointer()) - return getNullPointer(PT, DestType); + if (isa<llvm::PointerType>(DestTy)) { // Convert the integer to a pointer-sized integer before converting it // to a pointer. C = llvm::ConstantExpr::getIntegerCast( @@ -1518,7 +1510,7 @@ static llvm::Constant *EmitNullConstantF const CXXRecordDecl *base); static llvm::Constant *EmitNullConstant(CodeGenModule &CGM, - const RecordDecl *record, + const CXXRecordDecl *record, bool asCompleteObject) { const CGRecordLayout &layout = CGM.getTypes().getCGRecordLayout(record); llvm::StructType *structure = @@ -1528,29 +1520,25 @@ static llvm::Constant *EmitNullConstant( unsigned numElements = structure->getNumElements(); std::vector<llvm::Constant *> elements(numElements); - auto CXXR = dyn_cast<CXXRecordDecl>(record); // Fill in all the bases. - if (CXXR) { - for (const auto &I : CXXR->bases()) { - if (I.isVirtual()) { - // Ignore virtual bases; if we're laying out for a complete - // object, we'll lay these out later. - continue; - } + for (const auto &I : record->bases()) { + if (I.isVirtual()) { + // Ignore virtual bases; if we're laying out for a complete + // object, we'll lay these out later. + continue; + } - const CXXRecordDecl *base = - cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl()); + const CXXRecordDecl *base = + cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl()); - // Ignore empty bases. - if (base->isEmpty() || - CGM.getContext().getASTRecordLayout(base).getNonVirtualSize() - .isZero()) - continue; - - unsigned fieldIndex = layout.getNonVirtualBaseLLVMFieldNo(base); - llvm::Type *baseType = structure->getElementType(fieldIndex); - elements[fieldIndex] = EmitNullConstantForBase(CGM, baseType, base); - } + // Ignore empty bases. + if (base->isEmpty() || + CGM.getContext().getASTRecordLayout(base).getNonVirtualSize().isZero()) + continue; + + unsigned fieldIndex = layout.getNonVirtualBaseLLVMFieldNo(base); + llvm::Type *baseType = structure->getElementType(fieldIndex); + elements[fieldIndex] = EmitNullConstantForBase(CGM, baseType, base); } // Fill in all the fields. @@ -1574,8 +1562,8 @@ static llvm::Constant *EmitNullConstant( } // Fill in the virtual bases, if we're working with the complete object. - if (CXXR && asCompleteObject) { - for (const auto &I : CXXR->vbases()) { + if (asCompleteObject) { + for (const auto &I : record->vbases()) { const CXXRecordDecl *base = cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl()); @@ -1617,10 +1605,6 @@ static llvm::Constant *EmitNullConstantF } llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) { - if (T->getAs<PointerType>()) - return getNullPointer( - cast<llvm::PointerType>(getTypes().ConvertTypeForMem(T)), T); - if (getTypes().isZeroInitializable(T)) return llvm::Constant::getNullValue(getTypes().ConvertTypeForMem(T)); @@ -1636,8 +1620,10 @@ llvm::Constant *CodeGenModule::EmitNullC return llvm::ConstantArray::get(ATy, Array); } - if (const RecordType *RT = T->getAs<RecordType>()) - return ::EmitNullConstant(*this, RT->getDecl(), /*complete object*/ true); + if (const RecordType *RT = T->getAs<RecordType>()) { + const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); + return ::EmitNullConstant(*this, RD, /*complete object*/ true); + } assert(T->isMemberDataPointerType() && "Should only see pointers to data members here!"); Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=289713&r1=289712&r2=289713&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original) +++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Wed Dec 14 15:38:18 2016 @@ -19,7 +19,6 @@ #include "TargetInfo.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" -#include "clang/AST/Expr.h" #include "clang/AST/RecordLayout.h" #include "clang/AST/StmtVisitor.h" #include "clang/Basic/TargetInfo.h" @@ -172,9 +171,9 @@ public: } /// EmitPointerToBoolConversion - Perform a pointer to boolean conversion. - Value *EmitPointerToBoolConversion(Value *V, QualType QT) { - Value *Zero = CGF.CGM.getNullPointer(cast<llvm::PointerType>(V->getType()), QT); - + Value *EmitPointerToBoolConversion(Value *V) { + Value *Zero = llvm::ConstantPointerNull::get( + cast<llvm::PointerType>(V->getType())); return Builder.CreateICmpNE(V, Zero, "tobool"); } @@ -598,7 +597,7 @@ Value *ScalarExprEmitter::EmitConversion return EmitIntToBoolConversion(Src); assert(isa<llvm::PointerType>(Src->getType())); - return EmitPointerToBoolConversion(Src, SrcType); + return EmitPointerToBoolConversion(Src); } void ScalarExprEmitter::EmitFloatConversionCheck( @@ -1401,23 +1400,11 @@ Value *ScalarExprEmitter::VisitCastExpr( return Builder.CreateBitCast(Src, DstTy); } case CK_AddressSpaceConversion: { - Expr::EvalResult Result; - if (E->EvaluateAsRValue(Result, CGF.getContext()) && - Result.Val.isNullPointer()) { - // If E has side effect, it is emitted even if its final result is a - // null pointer. In that case, a DCE pass should be able to - // eliminate the useless instructions emitted during translating E. - if (Result.HasSideEffects) - Visit(E); - return CGF.CGM.getNullPointer(cast<llvm::PointerType>( - ConvertType(DestTy)), DestTy); - } + Value *Src = Visit(const_cast<Expr*>(E)); // Since target may map different address spaces in AST to the same address // space, an address space conversion may end up as a bitcast. - auto *Src = Visit(E); - return CGF.CGM.getTargetCodeGenInfo().performAddrSpaceCast(CGF, Src, - E->getType(), - DestTy); + return Builder.CreatePointerBitCastOrAddrSpaceCast(Src, + ConvertType(DestTy)); } case CK_AtomicToNonAtomic: case CK_NonAtomicToAtomic: @@ -1472,8 +1459,8 @@ Value *ScalarExprEmitter::VisitCastExpr( if (MustVisitNullValue(E)) (void) Visit(E); - return CGF.CGM.getNullPointer(cast<llvm::PointerType>(ConvertType(DestTy)), - DestTy); + return llvm::ConstantPointerNull::get( + cast<llvm::PointerType>(ConvertType(DestTy))); case CK_NullToMemberPointer: { if (MustVisitNullValue(E)) @@ -1566,7 +1553,7 @@ Value *ScalarExprEmitter::VisitCastExpr( case CK_IntegralToBoolean: return EmitIntToBoolConversion(Visit(E)); case CK_PointerToBoolean: - return EmitPointerToBoolConversion(Visit(E), E->getType()); + return EmitPointerToBoolConversion(Visit(E)); case CK_FloatingToBoolean: return EmitFloatToBoolConversion(Visit(E)); case CK_MemberPointerToBoolean: { Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=289713&r1=289712&r2=289713&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original) +++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Wed Dec 14 15:38:18 2016 @@ -2611,16 +2611,9 @@ void CodeGenModule::EmitGlobalVarDefinit else GV->setDLLStorageClass(llvm::GlobalVariable::DefaultStorageClass); - if (Linkage == llvm::GlobalVariable::CommonLinkage) { + if (Linkage == llvm::GlobalVariable::CommonLinkage) // common vars aren't constant even if declared const. GV->setConstant(false); - // Tentative definition of global variables may be initialized with - // non-zero null pointers. In this case they should have weak linkage - // since common linkage must have zero initializer and must not have - // explicit section therefore cannot have non-zero initial value. - if (!GV->getInitializer()->isNullValue()) - GV->setLinkage(llvm::GlobalVariable::WeakAnyLinkage); - } setNonAliasAttributes(D, GV); Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=289713&r1=289712&r2=289713&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CodeGenModule.h (original) +++ cfe/trunk/lib/CodeGen/CodeGenModule.h Wed Dec 14 15:38:18 2016 @@ -1155,11 +1155,6 @@ public: llvm::Value * createOpenCLIntToSamplerConversion(const Expr *E, CodeGenFunction &CGF); - /// Get target specific null pointer. - /// \param T is the LLVM type of the null pointer. - /// \param QT is the clang QualType of the null pointer. - llvm::Constant *getNullPointer(llvm::PointerType *T, QualType QT); - private: llvm::Constant * GetOrCreateLLVMFunction(StringRef MangledName, llvm::Type *Ty, GlobalDecl D, Modified: cfe/trunk/lib/CodeGen/CodeGenTypes.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenTypes.cpp?rev=289713&r1=289712&r2=289713&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CodeGenTypes.cpp (original) +++ cfe/trunk/lib/CodeGen/CodeGenTypes.cpp Wed Dec 14 15:38:18 2016 @@ -736,14 +736,10 @@ CodeGenTypes::getCGRecordLayout(const Re return *Layout; } -bool CodeGenTypes::isPointerZeroInitializable(QualType T) { - assert (T->getAs<PointerType>() && "Invalid type"); - return isZeroInitializable(T); -} - bool CodeGenTypes::isZeroInitializable(QualType T) { - if (T->getAs<PointerType>()) - return Context.getTargetNullPointerValue(T) == 0; + // No need to check for member pointers when not compiling C++. + if (!Context.getLangOpts().CPlusPlus) + return true; if (const auto *AT = Context.getAsArrayType(T)) { if (isa<IncompleteArrayType>(AT)) @@ -757,7 +753,7 @@ bool CodeGenTypes::isZeroInitializable(Q // Records are non-zero-initializable if they contain any // non-zero-initializable subobjects. if (const RecordType *RT = T->getAs<RecordType>()) { - auto RD = cast<RecordDecl>(RT->getDecl()); + const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); return isZeroInitializable(RD); } Modified: cfe/trunk/lib/CodeGen/CodeGenTypes.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenTypes.h?rev=289713&r1=289712&r2=289713&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CodeGenTypes.h (original) +++ cfe/trunk/lib/CodeGen/CodeGenTypes.h Wed Dec 14 15:38:18 2016 @@ -352,10 +352,6 @@ public: // These are internal details o /// zero-initialized (in the C++ sense) with an LLVM zeroinitializer. bool isZeroInitializable(QualType T); - /// Check if the pointer type can be zero-initialized (in the C++ sense) - /// with an LLVM zeroinitializer. - bool isPointerZeroInitializable(QualType T); - /// IsZeroInitializable - Return whether a record type can be /// zero-initialized (in the C++ sense) with an LLVM zeroinitializer. bool isZeroInitializable(const RecordDecl *RD); Modified: cfe/trunk/lib/CodeGen/TargetInfo.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/TargetInfo.cpp?rev=289713&r1=289712&r2=289713&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/TargetInfo.cpp (original) +++ cfe/trunk/lib/CodeGen/TargetInfo.cpp Wed Dec 14 15:38:18 2016 @@ -401,20 +401,6 @@ unsigned TargetCodeGenInfo::getOpenCLKer return llvm::CallingConv::C; } -llvm::Constant *TargetCodeGenInfo::getNullPointer(const CodeGen::CodeGenModule &CGM, - llvm::PointerType *T, QualType QT) const { - return llvm::ConstantPointerNull::get(T); -} - -llvm::Value *TargetCodeGenInfo::performAddrSpaceCast( - CodeGen::CodeGenFunction &CGF, llvm::Value *Src, QualType SrcTy, - QualType DestTy) const { - // Since target may map different address spaces in AST to the same address - // space, an address space conversion may end up as a bitcast. - return CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Src, - CGF.ConvertType(DestTy)); -} - static bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays); /// isEmptyField - Return true iff a the field is "empty", that is it @@ -7089,10 +7075,8 @@ public: void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M) const override; unsigned getOpenCLKernelCallingConv() const override; - - llvm::Constant *getNullPointer(const CodeGen::CodeGenModule &CGM, - llvm::PointerType *T, QualType QT) const override; }; + } static void appendOpenCLVersionMD (CodeGen::CodeGenModule &CGM); @@ -7156,24 +7140,6 @@ unsigned AMDGPUTargetCodeGenInfo::getOpe return llvm::CallingConv::AMDGPU_KERNEL; } -// Currently LLVM assumes null pointers always have value 0, -// which results in incorrectly transformed IR. Therefore, instead of -// emitting null pointers in private and local address spaces, a null -// pointer in generic address space is emitted which is casted to a -// pointer in local or private address space. -llvm::Constant *AMDGPUTargetCodeGenInfo::getNullPointer( - const CodeGen::CodeGenModule &CGM, llvm::PointerType *PT, - QualType QT) const { - if (CGM.getContext().getTargetNullPointerValue(QT) == 0) - return llvm::ConstantPointerNull::get(PT); - - auto &Ctx = CGM.getContext(); - auto NPT = llvm::PointerType::get(PT->getElementType(), - Ctx.getTargetAddressSpace(LangAS::opencl_generic)); - return llvm::ConstantExpr::getAddrSpaceCast( - llvm::ConstantPointerNull::get(NPT), PT); -} - //===----------------------------------------------------------------------===// // SPARC v8 ABI Implementation. // Based on the SPARC Compliance Definition version 2.4.1. Modified: cfe/trunk/lib/CodeGen/TargetInfo.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/TargetInfo.h?rev=289713&r1=289712&r2=289713&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/TargetInfo.h (original) +++ cfe/trunk/lib/CodeGen/TargetInfo.h Wed Dec 14 15:38:18 2016 @@ -220,22 +220,6 @@ public: /// Get LLVM calling convention for OpenCL kernel. virtual unsigned getOpenCLKernelCallingConv() const; - - /// Get target specific null pointer. - /// \param T is the LLVM type of the null pointer. - /// \param QT is the clang QualType of the null pointer. - /// \return ConstantPointerNull with the given type \p T. - /// Each target can override it to return its own desired constant value. - virtual llvm::Constant *getNullPointer(const CodeGen::CodeGenModule &CGM, - llvm::PointerType *T, QualType QT) const; - - /// Perform address space cast of an expression of pointer type. - /// \param V is the LLVM value to be casted to another address space. - /// \param SrcTy is the QualType of \p V. - /// \param DestTy is the destination QualType. - virtual llvm::Value *performAddrSpaceCast(CodeGen::CodeGenFunction &CGF, - llvm::Value *V, QualType SrcTy, QualType DestTy) const; - }; } // namespace CodeGen Removed: cfe/trunk/test/CodeGenOpenCL/amdgpu-nullptr.cl URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenOpenCL/amdgpu-nullptr.cl?rev=289712&view=auto ============================================================================== --- cfe/trunk/test/CodeGenOpenCL/amdgpu-nullptr.cl (original) +++ cfe/trunk/test/CodeGenOpenCL/amdgpu-nullptr.cl (removed) @@ -1,534 +0,0 @@ -// RUN: %clang_cc1 %s -cl-std=CL2.0 -include opencl-c.h -triple amdgcn -emit-llvm -o - | FileCheck %s -// RUN: %clang_cc1 %s -O0 -cl-std=CL2.0 -include opencl-c.h -triple amdgcn -emit-llvm -o - | FileCheck --check-prefix=NOOPT %s - -typedef struct { - private char *p1; - local char *p2; - constant char *p3; - global char *p4; - generic char *p5; -} StructTy1; - -typedef struct { - constant char *p3; - global char *p4; - generic char *p5; -} StructTy2; - -// LLVM requests global variable with common linkage to be initialized with zeroinitializer, therefore use -fno-common -// to suppress common linkage for tentative definition. - -// Test 0 as initializer. - -// CHECK: @private_p = local_unnamed_addr addrspace(1) global i8* addrspacecast (i8 addrspace(4)* null to i8*), align 4 -private char *private_p = 0; - -// CHECK: @local_p = local_unnamed_addr addrspace(1) global i8 addrspace(3)* addrspacecast (i8 addrspace(4)* null to i8 addrspace(3)*), align 4 -local char *local_p = 0; - -// CHECK: @global_p = local_unnamed_addr addrspace(1) global i8 addrspace(1)* null, align 4 -global char *global_p = 0; - -// CHECK: @constant_p = local_unnamed_addr addrspace(1) global i8 addrspace(2)* null, align 4 -constant char *constant_p = 0; - -// CHECK: @generic_p = local_unnamed_addr addrspace(1) global i8 addrspace(4)* null, align 4 -generic char *generic_p = 0; - -// Test NULL as initializer. - -// CHECK: @private_p_NULL = local_unnamed_addr addrspace(1) global i8* addrspacecast (i8 addrspace(4)* null to i8*), align 4 -private char *private_p_NULL = NULL; - -// CHECK: @local_p_NULL = local_unnamed_addr addrspace(1) global i8 addrspace(3)* addrspacecast (i8 addrspace(4)* null to i8 addrspace(3)*), align 4 -local char *local_p_NULL = NULL; - -// CHECK: @global_p_NULL = local_unnamed_addr addrspace(1) global i8 addrspace(1)* null, align 4 -global char *global_p_NULL = NULL; - -// CHECK: @constant_p_NULL = local_unnamed_addr addrspace(1) global i8 addrspace(2)* null, align 4 -constant char *constant_p_NULL = NULL; - -// CHECK: @generic_p_NULL = local_unnamed_addr addrspace(1) global i8 addrspace(4)* null, align 4 -generic char *generic_p_NULL = NULL; - -// Test constant folding of null pointer. -// A null pointer should be folded to a null pointer in the target address space. - -// CHECK: @fold_generic = local_unnamed_addr addrspace(1) global i32 addrspace(4)* null, align 4 -generic int *fold_generic = (global int*)(generic float*)(private char*)0; - -// CHECK: @fold_priv = local_unnamed_addr addrspace(1) global i16* addrspacecast (i16 addrspace(4)* null to i16*), align 4 -private short *fold_priv = (private short*)(generic int*)(global void*)0; - -// CHECK: @fold_priv_arith = local_unnamed_addr addrspace(1) global i8* inttoptr (i32 9 to i8*), align 4 -private char *fold_priv_arith = (private char*)0 + 10; - -// CHECK: @fold_int = local_unnamed_addr addrspace(1) global i32 13, align 4 -int fold_int = (int)(private void*)(generic char*)(global int*)0 + 14; - -// CHECK: @fold_int2 = local_unnamed_addr addrspace(1) global i32 12, align 4 -int fold_int2 = (int) ((private void*)0 + 13); - -// CHECK: @fold_int3 = local_unnamed_addr addrspace(1) global i32 -1, align 4 -int fold_int3 = (int) ((private int*)0); - -// CHECK: @fold_int4 = local_unnamed_addr addrspace(1) global i32 7, align 4 -int fold_int4 = (int) &((private int*)0)[2]; - -// CHECK: @fold_int5 = local_unnamed_addr addrspace(1) global i32 3, align 4 -int fold_int5 = (int) &((private StructTy1*)0)->p2; - -// Test static variable initialization. - -// NOOPT: @test_static_var.sp1 = internal addrspace(1) global i8* addrspacecast (i8 addrspace(4)* null to i8*), align 4 -// NOOPT: @test_static_var.sp2 = internal addrspace(1) global i8* addrspacecast (i8 addrspace(4)* null to i8*), align 4 -// NOOPT: @test_static_var.sp3 = internal addrspace(1) global i8* addrspacecast (i8 addrspace(4)* null to i8*), align 4 -// NOOPT: @test_static_var.sp4 = internal addrspace(1) global i8* null, align 4 -// NOOPT: @test_static_var.sp5 = internal addrspace(1) global i8* null, align 4 -// NOOPT: @test_static_var.SS1 = internal addrspace(1) global %struct.StructTy1 { i8* addrspacecast (i8 addrspace(4)* null to i8*), i8 addrspace(3)* addrspacecast (i8 addrspace(4)* null to i8 addrspace(3)*), i8 addrspace(2)* null, i8 addrspace(1)* null, i8 addrspace(4)* null }, align 4 -// NOOPT: @test_static_var.SS2 = internal addrspace(1) global %struct.StructTy2 zeroinitializer, align 4 - -void test_static_var(void) { - static private char *sp1 = 0; - static private char *sp2 = NULL; - static private char *sp3; - static private char *sp4 = (private char*)((void)0, 0); - const int x = 0; - static private char *sp5 = (private char*)x; - static StructTy1 SS1; - static StructTy2 SS2; -} - -// Test function-scope variable initialization. -// NOOPT-LABEL: test_func_scope_var -// NOOPT: store i8* addrspacecast (i8 addrspace(4)* null to i8*), i8** %sp1, align 4 -// NOOPT: store i8* addrspacecast (i8 addrspace(4)* null to i8*), i8** %sp2, align 4 -// NOOPT: store i8* null, i8** %sp3, align 4 -// NOOPT: store i8* null, i8** %sp4, align 4 -// NOOPT: %[[SS1:.*]] = bitcast %struct.StructTy1* %SS1 to i8* -// NOOPT: call void @llvm.memcpy.p0i8.p2i8.i64(i8* %[[SS1]], i8 addrspace(2)* bitcast (%struct.StructTy1 addrspace(2)* @test_func_scope_var.SS1 to i8 addrspace(2)*), i64 32, i32 4, i1 false) -// NOOPT: %[[SS2:.*]] = bitcast %struct.StructTy2* %SS2 to i8* -// NOOPT: call void @llvm.memset.p0i8.i64(i8* %[[SS2]], i8 0, i64 24, i32 4, i1 false) - -void test_func_scope_var(void) { - private char *sp1 = 0; - private char *sp2 = NULL; - private char *sp3 = (private char*)((void)0, 0); - const int x = 0; - private char *sp4 = (private char*)x; - StructTy1 SS1 = {0, 0, 0, 0, 0}; - StructTy2 SS2 = {0, 0, 0}; -} - -// Test default initialization of pointers. - -// Tentative definition of global variables with non-zero initializer -// cannot have common linkage since common linkage requires zero initialization -// and does not have explicit section. - -// CHECK: @p1 = weak local_unnamed_addr addrspace(1) global i8* addrspacecast (i8 addrspace(4)* null to i8*), align 4 -private char *p1; - -// CHECK: @p2 = weak local_unnamed_addr addrspace(1) global i8 addrspace(3)* addrspacecast (i8 addrspace(4)* null to i8 addrspace(3)*), align 4 -local char *p2; - -// CHECK: @p3 = common local_unnamed_addr addrspace(1) global i8 addrspace(2)* null, align 4 -constant char *p3; - -// CHECK: @p4 = common local_unnamed_addr addrspace(1) global i8 addrspace(1)* null, align 4 -global char *p4; - -// CHECK: @p5 = common local_unnamed_addr addrspace(1) global i8 addrspace(4)* null, align 4 -generic char *p5; - -// Test default initialization of sturcture. - -// CHECK: @S1 = weak local_unnamed_addr addrspace(1) global %struct.StructTy1 { i8* addrspacecast (i8 addrspace(4)* null to i8*), i8 addrspace(3)* addrspacecast (i8 addrspace(4)* null to i8 addrspace(3)*), i8 addrspace(2)* null, i8 addrspace(1)* null, i8 addrspace(4)* null }, align 4 -StructTy1 S1; - -// CHECK: @S2 = common local_unnamed_addr addrspace(1) global %struct.StructTy2 zeroinitializer, align 4 -StructTy2 S2; - -// Test default initialization of array. -// CHECK: @A1 = weak local_unnamed_addr addrspace(1) global [2 x %struct.StructTy1] [%struct.StructTy1 { i8* addrspacecast (i8 addrspace(4)* null to i8*), i8 addrspace(3)* addrspacecast (i8 addrspace(4)* null to i8 addrspace(3)*), i8 addrspace(2)* null, i8 addrspace(1)* null, i8 addrspace(4)* null }, %struct.StructTy1 { i8* addrspacecast (i8 addrspace(4)* null to i8*), i8 addrspace(3)* addrspacecast (i8 addrspace(4)* null to i8 addrspace(3)*), i8 addrspace(2)* null, i8 addrspace(1)* null, i8 addrspace(4)* null }], align 4 -StructTy1 A1[2]; - -// CHECK: @A2 = common local_unnamed_addr addrspace(1) global [2 x %struct.StructTy2] zeroinitializer, align 4 -StructTy2 A2[2]; - -// Test comparison with 0. - -// CHECK-LABEL: cmp_private -// CHECK: icmp eq i8* %p, addrspacecast (i8 addrspace(4)* null to i8*) -void cmp_private(private char* p) { - if (p != 0) - *p = 0; -} - -// CHECK-LABEL: cmp_local -// CHECK: icmp eq i8 addrspace(3)* %p, addrspacecast (i8 addrspace(4)* null to i8 addrspace(3)*) -void cmp_local(local char* p) { - if (p != 0) - *p = 0; -} - -// CHECK-LABEL: cmp_global -// CHECK: icmp eq i8 addrspace(1)* %p, null -void cmp_global(global char* p) { - if (p != 0) - *p = 0; -} - -// CHECK-LABEL: cmp_constant -// CHECK: icmp eq i8 addrspace(2)* %p, null -char cmp_constant(constant char* p) { - if (p != 0) - return *p; - else - return 0; -} - -// CHECK-LABEL: cmp_generic -// CHECK: icmp eq i8 addrspace(4)* %p, null -void cmp_generic(generic char* p) { - if (p != 0) - *p = 0; -} - -// Test comparison with NULL. - -// CHECK-LABEL: cmp_NULL_private -// CHECK: icmp eq i8* %p, addrspacecast (i8 addrspace(4)* null to i8*) -void cmp_NULL_private(private char* p) { - if (p != NULL) - *p = 0; -} - -// CHECK-LABEL: cmp_NULL_local -// CHECK: icmp eq i8 addrspace(3)* %p, addrspacecast (i8 addrspace(4)* null to i8 addrspace(3)*) -void cmp_NULL_local(local char* p) { - if (p != NULL) - *p = 0; -} - -// CHECK-LABEL: cmp_NULL_global -// CHECK: icmp eq i8 addrspace(1)* %p, null -void cmp_NULL_global(global char* p) { - if (p != NULL) - *p = 0; -} - -// CHECK-LABEL: cmp_NULL_constant -// CHECK: icmp eq i8 addrspace(2)* %p, null -char cmp_NULL_constant(constant char* p) { - if (p != NULL) - return *p; - else - return 0; -} - -// CHECK-LABEL: cmp_NULL_generic -// CHECK: icmp eq i8 addrspace(4)* %p, null -void cmp_NULL_generic(generic char* p) { - if (p != NULL) - *p = 0; -} - -// Test storage 0 as null pointer. -// CHECK-LABEL: test_storage_null_pointer -// CHECK: store i8* addrspacecast (i8 addrspace(4)* null to i8*), i8* addrspace(4)* %arg_private -// CHECK: store i8 addrspace(3)* addrspacecast (i8 addrspace(4)* null to i8 addrspace(3)*), i8 addrspace(3)* addrspace(4)* %arg_local -// CHECK: store i8 addrspace(1)* null, i8 addrspace(1)* addrspace(4)* %arg_global -// CHECK: store i8 addrspace(2)* null, i8 addrspace(2)* addrspace(4)* %arg_constant -// CHECK: store i8 addrspace(4)* null, i8 addrspace(4)* addrspace(4)* %arg_generic -void test_storage_null_pointer(private char** arg_private, - local char** arg_local, - global char** arg_global, - constant char** arg_constant, - generic char** arg_generic) { - *arg_private = 0; - *arg_local = 0; - *arg_global = 0; - *arg_constant = 0; - *arg_generic = 0; -} - -// Test storage NULL as null pointer. -// CHECK-LABEL: test_storage_null_pointer_NULL -// CHECK: store i8* addrspacecast (i8 addrspace(4)* null to i8*), i8* addrspace(4)* %arg_private -// CHECK: store i8 addrspace(3)* addrspacecast (i8 addrspace(4)* null to i8 addrspace(3)*), i8 addrspace(3)* addrspace(4)* %arg_local -// CHECK: store i8 addrspace(1)* null, i8 addrspace(1)* addrspace(4)* %arg_global -// CHECK: store i8 addrspace(2)* null, i8 addrspace(2)* addrspace(4)* %arg_constant -// CHECK: store i8 addrspace(4)* null, i8 addrspace(4)* addrspace(4)* %arg_generic -void test_storage_null_pointer_NULL(private char** arg_private, - local char** arg_local, - global char** arg_global, - constant char** arg_constant, - generic char** arg_generic) { - *arg_private = NULL; - *arg_local = NULL; - *arg_global = NULL; - *arg_constant = NULL; - *arg_generic = NULL; -} - -// Test pass null pointer to function as argument. -void test_pass_null_pointer_arg_calee(private char* arg_private, - local char* arg_local, - global char* arg_global, - constant char* arg_constant, - generic char* arg_generic); - -// CHECK-LABEL: test_pass_null_pointer_arg -// CHECK: call void @test_pass_null_pointer_arg_calee(i8* addrspacecast (i8 addrspace(4)* null to i8*), i8 addrspace(3)* addrspacecast (i8 addrspace(4)* null to i8 addrspace(3)*), i8 addrspace(1)* null, i8 addrspace(2)* null, i8 addrspace(4)* null) -// CHECK: call void @test_pass_null_pointer_arg_calee(i8* addrspacecast (i8 addrspace(4)* null to i8*), i8 addrspace(3)* addrspacecast (i8 addrspace(4)* null to i8 addrspace(3)*), i8 addrspace(1)* null, i8 addrspace(2)* null, i8 addrspace(4)* null) -void test_pass_null_pointer_arg(void) { - test_pass_null_pointer_arg_calee(0, 0, 0, 0, 0); - test_pass_null_pointer_arg_calee(NULL, NULL, NULL, NULL, NULL); -} - -// Test cast null pointer to size_t. -void test_cast_null_pointer_to_sizet_calee(size_t arg_private, - size_t arg_local, - size_t arg_global, - size_t arg_constant, - size_t arg_generic); - -// CHECK-LABEL: test_cast_null_pointer_to_sizet -// CHECK: call void @test_cast_null_pointer_to_sizet_calee(i64 ptrtoint (i8* addrspacecast (i8 addrspace(4)* null to i8*) to i64), i64 ptrtoint (i8 addrspace(3)* addrspacecast (i8 addrspace(4)* null to i8 addrspace(3)*) to i64), i64 0, i64 0, i64 0) -// CHECK: call void @test_cast_null_pointer_to_sizet_calee(i64 ptrtoint (i8* addrspacecast (i8 addrspace(4)* null to i8*) to i64), i64 ptrtoint (i8 addrspace(3)* addrspacecast (i8 addrspace(4)* null to i8 addrspace(3)*) to i64), i64 0, i64 0, i64 0) -void test_cast_null_pointer_to_sizet(void) { - test_cast_null_pointer_to_sizet_calee((size_t)((private char*)0), - (size_t)((local char*)0), - (size_t)((global char*)0), - (size_t)((constant char*)0), - (size_t)((generic char*)0)); - test_cast_null_pointer_to_sizet_calee((size_t)((private char*)NULL), - (size_t)((local char*)NULL), - (size_t)((global char*)NULL), - (size_t)((constant char*)0), // NULL cannot be casted to constant pointer since it is defined as a generic pointer - (size_t)((generic char*)NULL)); -} - -// Test comparision between null pointers. -#define TEST_EQ00(addr1, addr2) int test_eq00_##addr1##_##addr2(void) { return (addr1 char*)0 == (addr2 char*)0; } -#define TEST_EQ0N(addr1, addr2) int test_eq0N_##addr1##_##addr2(void) { return (addr1 char*)0 == (addr2 char*)NULL; } -#define TEST_EQN0(addr1, addr2) int test_eqN0_##addr1##_##addr2(void) { return (addr1 char*)NULL == (addr2 char*)0; } -#define TEST_EQNN(addr1, addr2) int test_eqNN_##addr1##_##addr2(void) { return (addr1 char*)0 == (addr2 char*)NULL; } -#define TEST_NE00(addr1, addr2) int test_ne00_##addr1##_##addr2(void) { return (addr1 char*)0 != (addr2 char*)0; } -#define TEST_NE0N(addr1, addr2) int test_ne0N_##addr1##_##addr2(void) { return (addr1 char*)0 != (addr2 char*)NULL; } -#define TEST_NEN0(addr1, addr2) int test_neN0_##addr1##_##addr2(void) { return (addr1 char*)NULL != (addr2 char*)0; } -#define TEST_NENN(addr1, addr2) int test_neNN_##addr1##_##addr2(void) { return (addr1 char*)0 != (addr2 char*)NULL; } -#define TEST(addr1, addr2) \ - TEST_EQ00(addr1, addr2) \ - TEST_EQ0N(addr1, addr2) \ - TEST_EQN0(addr1, addr2) \ - TEST_EQNN(addr1, addr2) \ - TEST_NE00(addr1, addr2) \ - TEST_NE0N(addr1, addr2) \ - TEST_NEN0(addr1, addr2) \ - TEST_NENN(addr1, addr2) - -// CHECK-LABEL: test_eq00_generic_private -// CHECK: ret i32 1 -// CHECK-LABEL: test_eq0N_generic_private -// CHECK: ret i32 1 -// CHECK-LABEL: test_eqN0_generic_private -// CHECK: ret i32 1 -// CHECK-LABEL: test_eqNN_generic_private -// CHECK: ret i32 1 -// CHECK-LABEL: test_ne00_generic_private -// CHECK: ret i32 0 -// CHECK-LABEL: test_ne0N_generic_private -// CHECK: ret i32 0 -// CHECK-LABEL: test_neN0_generic_private -// CHECK: ret i32 0 -// CHECK-LABEL: test_neNN_generic_private -// CHECK: ret i32 0 -TEST(generic, private) - -// CHECK-LABEL: test_eq00_generic_local -// CHECK: ret i32 1 -// CHECK-LABEL: test_eq0N_generic_local -// CHECK: ret i32 1 -// CHECK-LABEL: test_eqN0_generic_local -// CHECK: ret i32 1 -// CHECK-LABEL: test_eqNN_generic_local -// CHECK: ret i32 1 -// CHECK-LABEL: test_ne00_generic_local -// CHECK: ret i32 0 -// CHECK-LABEL: test_ne0N_generic_local -// CHECK: ret i32 0 -// CHECK-LABEL: test_neN0_generic_local -// CHECK: ret i32 0 -// CHECK-LABEL: test_neNN_generic_local -// CHECK: ret i32 0 -TEST(generic, local) - -// CHECK-LABEL: test_eq00_generic_global -// CHECK: ret i32 1 -// CHECK-LABEL: test_eq0N_generic_global -// CHECK: ret i32 1 -// CHECK-LABEL: test_eqN0_generic_global -// CHECK: ret i32 1 -// CHECK-LABEL: test_eqNN_generic_global -// CHECK: ret i32 1 -// CHECK-LABEL: test_ne00_generic_global -// CHECK: ret i32 0 -// CHECK-LABEL: test_ne0N_generic_global -// CHECK: ret i32 0 -// CHECK-LABEL: test_neN0_generic_global -// CHECK: ret i32 0 -// CHECK-LABEL: test_neNN_generic_global -// CHECK: ret i32 0 -TEST(generic, global) - -// CHECK-LABEL: test_eq00_generic_generic -// CHECK: ret i32 1 -// CHECK-LABEL: test_eq0N_generic_generic -// CHECK: ret i32 1 -// CHECK-LABEL: test_eqN0_generic_generic -// CHECK: ret i32 1 -// CHECK-LABEL: test_eqNN_generic_generic -// CHECK: ret i32 1 -// CHECK-LABEL: test_ne00_generic_generic -// CHECK: ret i32 0 -// CHECK-LABEL: test_ne0N_generic_generic -// CHECK: ret i32 0 -// CHECK-LABEL: test_neN0_generic_generic -// CHECK: ret i32 0 -// CHECK-LABEL: test_neNN_generic_generic -// CHECK: ret i32 0 -TEST(generic, generic) - -// CHECK-LABEL: test_eq00_constant_constant -// CHECK: ret i32 1 -TEST_EQ00(constant, constant) - -// Test cast to bool. - -// CHECK-LABEL: cast_bool_private -// CHECK: icmp eq i8* %p, addrspacecast (i8 addrspace(4)* null to i8*) -void cast_bool_private(private char* p) { - if (p) - *p = 0; -} - -// CHECK-LABEL: cast_bool_local -// CHECK: icmp eq i8 addrspace(3)* %p, addrspacecast (i8 addrspace(4)* null to i8 addrspace(3)*) -void cast_bool_local(local char* p) { - if (p) - *p = 0; -} - -// CHECK-LABEL: cast_bool_global -// CHECK: icmp eq i8 addrspace(1)* %p, null -void cast_bool_global(global char* p) { - if (p) - *p = 0; -} - -// CHECK-LABEL: cast_bool_constant -// CHECK: icmp eq i8 addrspace(2)* %p, null -char cast_bool_constant(constant char* p) { - if (p) - return *p; - else - return 0; -} - -// CHECK-LABEL: cast_bool_generic -// CHECK: icmp eq i8 addrspace(4)* %p, null -void cast_bool_generic(generic char* p) { - if (p) - *p = 0; -} - -// Test initialize a struct using memset. -// For large structures which is mostly zero, clang generats llvm.memset for -// the zero part and store for non-zero members. -typedef struct { - long a, b, c, d; - private char *p; -} StructTy3; - -// CHECK-LABEL: test_memset -// CHECK: call void @llvm.memset.p0i8.i64(i8* {{.*}}, i8 0, i64 32, i32 8, i1 false) -// CHECK: store i8* addrspacecast (i8 addrspace(4)* null to i8*), i8** {{.*}} -StructTy3 test_memset(void) { - StructTy3 S3 = {0, 0, 0, 0, 0}; - return S3; -} - -// Test casting literal 0 to pointer. -// A 0 literal casted to pointer should become a null pointer. - -// CHECK-LABEL: test_cast_0_to_ptr -// CHECK: ret i32* addrspacecast (i32 addrspace(4)* null to i32*) -private int* test_cast_0_to_ptr(void) { - return (private int*)0; -} - -// Test casting non-literal integer with 0 value to pointer. -// A non-literal integer expression with 0 value is casted to a pointer with -// zero value. - -// CHECK-LABEL: test_cast_int_to_ptr1 -// CHECK: ret i32* null -private int* test_cast_int_to_ptr1(void) { - return (private int*)((void)0, 0); -} - -// CHECK-LABEL: test_cast_int_to_ptr2 -// CHECK: ret i32* null -private int* test_cast_int_to_ptr2(void) { - int x = 0; - return (private int*)x; -} - -// Test logical operations. -// CHECK-LABEL: test_not_nullptr -// CHECK: ret i32 1 -int test_not_nullptr(void) { - return !(private char*)NULL; -} - -// CHECK-LABEL: test_and_nullptr -// CHECK: ret i32 0 -int test_and_nullptr(int a) { - return a && ((private char*)NULL); -} - -// CHECK-LABEL: test_not_ptr -// CHECK: %[[lnot:.*]] = icmp eq i8* %p, addrspacecast (i8 addrspace(4)* null to i8*) -// CHECK: %[[lnot_ext:.*]] = zext i1 %[[lnot]] to i32 -// CHECK: ret i32 %[[lnot_ext]] -int test_not_ptr(private char* p) { - return !p; -} -// CHECK-LABEL: test_and_ptr -// CHECK: %[[tobool:.*]] = icmp ne i8* %p1, addrspacecast (i8 addrspace(4)* null to i8*) -// CHECK: %[[tobool1:.*]] = icmp ne i8 addrspace(3)* %p2, addrspacecast (i8 addrspace(4)* null to i8 addrspace(3)*) -// CHECK: %[[res:.*]] = and i1 %[[tobool]], %[[tobool1]] -// CHECK: %[[land_ext:.*]] = zext i1 %[[res]] to i32 -// CHECK: ret i32 %[[land_ext]] -int test_and_ptr(private char* p1, local char* p2) { - return p1 && p2; -} - -// Test folding of null pointer in function scope. -// NOOPT-LABEL: test_fold -// NOOPT: call void @test_fold_callee -// NOOPT: store i32 addrspace(1)* null, i32 addrspace(1)** %glob, align 4 -// NOOPT: %{{.*}} = sub i64 %{{.*}}, 0 -// NOOPT: call void @test_fold_callee -// NOOPT: %{{.*}} = add nsw i64 %{{.*}}, sext (i32 ptrtoint (i32* addrspacecast (i32 addrspace(4)* null to i32*) to i32) to i64) -// NOOPT: %{{.*}} = sub nsw i64 %{{.*}}, 1 -void test_fold_callee(void); -void test_fold(void) { - global int* glob = (test_fold_callee(), (global int*)(generic char*)0); - long x = glob - (global int*)(generic char*)0; - x = x + (int)(test_fold_callee(), (private int*)(generic char*)(global short*)0); - x = x - (int)((private int*)0 == (private int*)(generic char*)0); -} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits