summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/APValue.cpp17
-rw-r--r--clang/lib/AST/ASTContext.cpp10
-rw-r--r--clang/lib/AST/ExprConstant.cpp57
-rw-r--r--clang/lib/Basic/Targets.cpp7
-rw-r--r--clang/lib/CodeGen/CGDecl.cpp2
-rw-r--r--clang/lib/CodeGen/CGExprAgg.cpp3
-rw-r--r--clang/lib/CodeGen/CGExprConstant.cpp62
-rw-r--r--clang/lib/CodeGen/CGExprScalar.cpp33
-rw-r--r--clang/lib/CodeGen/CodeGenModule.cpp9
-rw-r--r--clang/lib/CodeGen/CodeGenModule.h5
-rw-r--r--clang/lib/CodeGen/CodeGenTypes.cpp12
-rw-r--r--clang/lib/CodeGen/CodeGenTypes.h4
-rw-r--r--clang/lib/CodeGen/TargetInfo.cpp36
-rw-r--r--clang/lib/CodeGen/TargetInfo.h16
14 files changed, 212 insertions, 61 deletions
diff --git a/clang/lib/AST/APValue.cpp b/clang/lib/AST/APValue.cpp
index 89231599727..488ad3373ca 100644
--- a/clang/lib/AST/APValue.cpp
+++ b/clang/lib/AST/APValue.cpp
@@ -27,6 +27,7 @@ namespace {
CharUnits Offset;
unsigned PathLength;
unsigned CallIndex;
+ bool IsNullPtr;
};
}
@@ -149,10 +150,11 @@ APValue::APValue(const APValue &RHS) : Kind(Uninitialized) {
MakeLValue();
if (RHS.hasLValuePath())
setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), RHS.getLValuePath(),
- RHS.isLValueOnePastTheEnd(), RHS.getLValueCallIndex());
+ RHS.isLValueOnePastTheEnd(), RHS.getLValueCallIndex(),
+ RHS.isNullPointer());
else
setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), NoLValuePath(),
- RHS.getLValueCallIndex());
+ RHS.getLValueCallIndex(), RHS.isNullPointer());
break;
case Array:
MakeArray(RHS.getArrayInitializedElts(), RHS.getArraySize());
@@ -579,8 +581,13 @@ unsigned APValue::getLValueCallIndex() const {
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) {
+ unsigned CallIndex, bool IsNullPtr) {
assert(isLValue() && "Invalid accessor");
LV &LVal = *((LV*)(char*)Data.buffer);
LVal.BaseAndIsOnePastTheEnd.setPointer(B);
@@ -588,11 +595,12 @@ void APValue::setLValue(LValueBase B, const CharUnits &O, NoLValuePath,
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) {
+ unsigned CallIndex, bool IsNullPtr) {
assert(isLValue() && "Invalid accessor");
LV &LVal = *((LV*)(char*)Data.buffer);
LVal.BaseAndIsOnePastTheEnd.setPointer(B);
@@ -601,6 +609,7 @@ void APValue::setLValue(LValueBase B, const CharUnits &O,
LVal.CallIndex = CallIndex;
LVal.resizePath(Path.size());
memcpy(LVal.getPath(), Path.data(), Path.size() * sizeof(LValuePathEntry));
+ LVal.IsNullPtr = IsNullPtr;
}
const ValueDecl *APValue::getMemberPointerDecl() const {
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 73ea66e98e8..7a98ac4c6e9 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -9434,6 +9434,16 @@ ASTContext::ObjCMethodsAreEqual(const ObjCMethodDecl *MethodDecl,
}
+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
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 36f5e6aae55..0abdaa879ec 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -1088,6 +1088,7 @@ namespace {
unsigned InvalidBase : 1;
unsigned CallIndex : 31;
SubobjectDesignator Designator;
+ bool IsNullPtr;
const APValue::LValueBase getLValueBase() const { return Base; }
CharUnits &getLValueOffset() { return Offset; }
@@ -1095,13 +1096,15 @@ 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);
+ V = APValue(Base, Offset, APValue::NoLValuePath(), CallIndex,
+ IsNullPtr);
else
V = APValue(Base, Offset, Designator.Entries,
- Designator.IsOnePastTheEnd, CallIndex);
+ Designator.IsOnePastTheEnd, CallIndex, IsNullPtr);
}
void setFrom(ASTContext &Ctx, const APValue &V) {
assert(V.isLValue());
@@ -1110,14 +1113,17 @@ namespace {
InvalidBase = false;
CallIndex = V.getLValueCallIndex();
Designator = SubobjectDesignator(Ctx, V);
+ IsNullPtr = V.isNullPointer();
}
- void set(APValue::LValueBase B, unsigned I = 0, bool BInvalid = false) {
+ void set(APValue::LValueBase B, unsigned I = 0, bool BInvalid = false,
+ bool IsNullPtr_ = false, uint64_t Offset_ = 0) {
Base = B;
- Offset = CharUnits::Zero();
+ Offset = CharUnits::fromQuantity(Offset_);
InvalidBase = BInvalid;
CallIndex = I;
Designator = SubobjectDesignator(getType(B));
+ IsNullPtr = IsNullPtr_;
}
void setInvalid(APValue::LValueBase B, unsigned I = 0) {
@@ -1130,7 +1136,7 @@ namespace {
CheckSubobjectKind CSK) {
if (Designator.Invalid)
return false;
- if (!Base) {
+ if (IsNullPtr) {
Info.CCEDiag(E, diag::note_constexpr_null_subobject)
<< CSK;
Designator.setInvalid();
@@ -1159,9 +1165,22 @@ namespace {
if (checkSubobject(Info, E, Imag ? CSK_Imag : CSK_Real))
Designator.addComplexUnchecked(EltTy, Imag);
}
- void adjustIndex(EvalInfo &Info, const Expr *E, uint64_t N) {
- if (N && checkNullPointer(Info, E, CSK_ArrayIndex))
- Designator.adjustIndex(Info, E, N);
+ 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();
}
};
@@ -2036,7 +2055,7 @@ static bool HandleLValueMember(EvalInfo &Info, const Expr *E, LValue &LVal,
}
unsigned I = FD->getFieldIndex();
- LVal.Offset += Info.Ctx.toCharUnitsFromBits(RL->getFieldOffset(I));
+ LVal.adjustOffset(Info.Ctx.toCharUnitsFromBits(RL->getFieldOffset(I)));
LVal.addDecl(Info, E, FD);
return true;
}
@@ -2090,9 +2109,7 @@ static bool HandleLValueArrayAdjustment(EvalInfo &Info, const Expr *E,
if (!HandleSizeof(Info, E->getExprLoc(), EltTy, SizeOfPointee))
return false;
- // Compute the new offset in the appropriate width.
- LVal.Offset += Adjustment * SizeOfPointee;
- LVal.adjustIndex(Info, E, Adjustment);
+ LVal.adjustOffsetAndIndex(Info, E, Adjustment, SizeOfPointee);
return true;
}
@@ -5081,7 +5098,9 @@ public:
return true;
}
bool ZeroInitialization(const Expr *E) {
- return Success((Expr*)nullptr);
+ auto Offset = Info.Ctx.getTargetNullPointerValue(E->getType());
+ Result.set((Expr*)nullptr, 0, false, true, Offset);
+ return true;
}
bool VisitBinaryOperator(const BinaryOperator *E);
@@ -5180,6 +5199,8 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) {
else
CCEDiag(E, diag::note_constexpr_invalid_cast) << 2;
}
+ if (E->getCastKind() == CK_AddressSpaceConversion && Result.IsNullPtr)
+ ZeroInitialization(E);
return true;
case CK_DerivedToBase:
@@ -5221,6 +5242,7 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) {
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.
@@ -8395,8 +8417,13 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) {
return true;
}
- APSInt AsInt = Info.Ctx.MakeIntValue(LV.getLValueOffset().getQuantity(),
- SrcType);
+ uint64_t V;
+ if (LV.isNullPointer())
+ V = Info.Ctx.getTargetNullPointerValue(SrcType);
+ else
+ V = LV.getLValueOffset().getQuantity();
+
+ APSInt AsInt = Info.Ctx.MakeIntValue(V, SrcType);
return Success(HandleIntToIntCast(Info, E, DestType, SrcType, AsInt), E);
}
diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp
index 91eabb36bd3..ee84089835b 100644
--- a/clang/lib/Basic/Targets.cpp
+++ b/clang/lib/Basic/Targets.cpp
@@ -2245,6 +2245,13 @@ 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[] = {
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 695e92ea1d0..46573477580 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -708,7 +708,7 @@ void CodeGenFunction::EmitScalarInit(const Expr *init, const ValueDecl *D,
}
auto ty = cast<llvm::PointerType>(tempLV.getAddress().getElementType());
- llvm::Value *zero = llvm::ConstantPointerNull::get(ty);
+ llvm::Value *zero = CGM.getNullPointer(ty, tempLV.getType());
// If __weak, we want to use a barrier under certain conditions.
if (lifetime == Qualifiers::OCL_Weak)
diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp
index e24a0853c80..35148bea001 100644
--- a/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/clang/lib/CodeGen/CGExprAgg.cpp
@@ -1052,7 +1052,8 @@ static bool isSimpleZero(const Expr *E, CodeGenFunction &CGF) {
return true;
// (int*)0 - Null pointer expressions.
if (const CastExpr *ICE = dyn_cast<CastExpr>(E))
- return ICE->getCastKind() == CK_NullToPointer;
+ return ICE->getCastKind() == CK_NullToPointer &&
+ CGF.getTypes().isPointerZeroInitializable(E->getType());
// '\0'
if (const CharacterLiteral *CL = dyn_cast<CharacterLiteral>(E))
return CL->getValue() == 0;
diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp
index 345e0a9216a..752f419f64e 100644
--- a/clang/lib/CodeGen/CGExprConstant.cpp
+++ b/clang/lib/CodeGen/CGExprConstant.cpp
@@ -16,6 +16,7 @@
#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"
@@ -1262,6 +1263,10 @@ llvm::Constant *CodeGenModule::EmitConstantExpr(const Expr *E,
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) {
@@ -1293,6 +1298,7 @@ llvm::Constant *CodeGenModule::EmitConstantValue(const APValue &Value,
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)) {
@@ -1323,7 +1329,9 @@ llvm::Constant *CodeGenModule::EmitConstantValue(const APValue &Value,
// Convert to the appropriate type; this could be an lvalue for
// an integer.
- if (isa<llvm::PointerType>(DestTy)) {
+ if (auto PT = dyn_cast<llvm::PointerType>(DestTy)) {
+ if (Value.isNullPointer())
+ return getNullPointer(PT, DestType);
// Convert the integer to a pointer-sized integer before converting it
// to a pointer.
C = llvm::ConstantExpr::getIntegerCast(
@@ -1510,7 +1518,7 @@ static llvm::Constant *EmitNullConstantForBase(CodeGenModule &CGM,
const CXXRecordDecl *base);
static llvm::Constant *EmitNullConstant(CodeGenModule &CGM,
- const CXXRecordDecl *record,
+ const RecordDecl *record,
bool asCompleteObject) {
const CGRecordLayout &layout = CGM.getTypes().getCGRecordLayout(record);
llvm::StructType *structure =
@@ -1520,25 +1528,29 @@ static llvm::Constant *EmitNullConstant(CodeGenModule &CGM,
unsigned numElements = structure->getNumElements();
std::vector<llvm::Constant *> elements(numElements);
+ auto CXXR = dyn_cast<CXXRecordDecl>(record);
// Fill in all the bases.
- 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;
- }
+ 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;
+ }
- 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.
@@ -1562,8 +1574,8 @@ static llvm::Constant *EmitNullConstant(CodeGenModule &CGM,
}
// Fill in the virtual bases, if we're working with the complete object.
- if (asCompleteObject) {
- for (const auto &I : record->vbases()) {
+ if (CXXR && asCompleteObject) {
+ for (const auto &I : CXXR->vbases()) {
const CXXRecordDecl *base =
cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl());
@@ -1605,6 +1617,10 @@ static llvm::Constant *EmitNullConstantForBase(CodeGenModule &CGM,
}
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));
@@ -1620,10 +1636,8 @@ llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) {
return llvm::ConstantArray::get(ATy, Array);
}
- if (const RecordType *RT = T->getAs<RecordType>()) {
- const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
- return ::EmitNullConstant(*this, RD, /*complete object*/ true);
- }
+ if (const RecordType *RT = T->getAs<RecordType>())
+ return ::EmitNullConstant(*this, RT->getDecl(), /*complete object*/ true);
assert(T->isMemberDataPointerType() &&
"Should only see pointers to data members here!");
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index e763e6ab020..e9bdbda34aa 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -19,6 +19,7 @@
#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"
@@ -171,9 +172,9 @@ public:
}
/// EmitPointerToBoolConversion - Perform a pointer to boolean conversion.
- Value *EmitPointerToBoolConversion(Value *V) {
- Value *Zero = llvm::ConstantPointerNull::get(
- cast<llvm::PointerType>(V->getType()));
+ Value *EmitPointerToBoolConversion(Value *V, QualType QT) {
+ Value *Zero = CGF.CGM.getNullPointer(cast<llvm::PointerType>(V->getType()), QT);
+
return Builder.CreateICmpNE(V, Zero, "tobool");
}
@@ -597,7 +598,7 @@ Value *ScalarExprEmitter::EmitConversionToBool(Value *Src, QualType SrcType) {
return EmitIntToBoolConversion(Src);
assert(isa<llvm::PointerType>(Src->getType()));
- return EmitPointerToBoolConversion(Src);
+ return EmitPointerToBoolConversion(Src, SrcType);
}
void ScalarExprEmitter::EmitFloatConversionCheck(
@@ -1400,11 +1401,23 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
return Builder.CreateBitCast(Src, DstTy);
}
case CK_AddressSpaceConversion: {
- Value *Src = Visit(const_cast<Expr*>(E));
+ 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);
+ }
// 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 Builder.CreatePointerBitCastOrAddrSpaceCast(Src,
- ConvertType(DestTy));
+ auto *Src = Visit(E);
+ return CGF.CGM.getTargetCodeGenInfo().performAddrSpaceCast(CGF, Src,
+ E->getType(),
+ DestTy);
}
case CK_AtomicToNonAtomic:
case CK_NonAtomicToAtomic:
@@ -1459,8 +1472,8 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
if (MustVisitNullValue(E))
(void) Visit(E);
- return llvm::ConstantPointerNull::get(
- cast<llvm::PointerType>(ConvertType(DestTy)));
+ return CGF.CGM.getNullPointer(cast<llvm::PointerType>(ConvertType(DestTy)),
+ DestTy);
case CK_NullToMemberPointer: {
if (MustVisitNullValue(E))
@@ -1553,7 +1566,7 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
case CK_IntegralToBoolean:
return EmitIntToBoolConversion(Visit(E));
case CK_PointerToBoolean:
- return EmitPointerToBoolConversion(Visit(E));
+ return EmitPointerToBoolConversion(Visit(E), E->getType());
case CK_FloatingToBoolean:
return EmitFloatToBoolConversion(Visit(E));
case CK_MemberPointerToBoolean: {
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 404cbae1d83..64c2bd673cc 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -2663,9 +2663,16 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D,
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);
diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h
index d4c096ed67b..f26c92d5670 100644
--- a/clang/lib/CodeGen/CodeGenModule.h
+++ b/clang/lib/CodeGen/CodeGenModule.h
@@ -1156,6 +1156,11 @@ 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,
diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp
index c92095bbbe6..b95b4fff573 100644
--- a/clang/lib/CodeGen/CodeGenTypes.cpp
+++ b/clang/lib/CodeGen/CodeGenTypes.cpp
@@ -736,10 +736,14 @@ CodeGenTypes::getCGRecordLayout(const RecordDecl *RD) {
return *Layout;
}
+bool CodeGenTypes::isPointerZeroInitializable(QualType T) {
+ assert (T->isAnyPointerType() && "Invalid type");
+ return isZeroInitializable(T);
+}
+
bool CodeGenTypes::isZeroInitializable(QualType T) {
- // No need to check for member pointers when not compiling C++.
- if (!Context.getLangOpts().CPlusPlus)
- return true;
+ if (T->getAs<PointerType>())
+ return Context.getTargetNullPointerValue(T) == 0;
if (const auto *AT = Context.getAsArrayType(T)) {
if (isa<IncompleteArrayType>(AT))
@@ -753,7 +757,7 @@ bool CodeGenTypes::isZeroInitializable(QualType T) {
// Records are non-zero-initializable if they contain any
// non-zero-initializable subobjects.
if (const RecordType *RT = T->getAs<RecordType>()) {
- const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ auto RD = cast<RecordDecl>(RT->getDecl());
return isZeroInitializable(RD);
}
diff --git a/clang/lib/CodeGen/CodeGenTypes.h b/clang/lib/CodeGen/CodeGenTypes.h
index 00df10dd138..2ce6591e4eb 100644
--- a/clang/lib/CodeGen/CodeGenTypes.h
+++ b/clang/lib/CodeGen/CodeGenTypes.h
@@ -352,6 +352,10 @@ public: // These are internal details of CGT that shouldn't be used externally.
/// 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);
diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp
index 38b164b113a..391eb53d250 100644
--- a/clang/lib/CodeGen/TargetInfo.cpp
+++ b/clang/lib/CodeGen/TargetInfo.cpp
@@ -401,6 +401,20 @@ unsigned TargetCodeGenInfo::getOpenCLKernelCallingConv() const {
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
@@ -7075,8 +7089,10 @@ 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);
@@ -7140,6 +7156,24 @@ unsigned AMDGPUTargetCodeGenInfo::getOpenCLKernelCallingConv() const {
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.
diff --git a/clang/lib/CodeGen/TargetInfo.h b/clang/lib/CodeGen/TargetInfo.h
index e46382596af..223d6d047af 100644
--- a/clang/lib/CodeGen/TargetInfo.h
+++ b/clang/lib/CodeGen/TargetInfo.h
@@ -220,6 +220,22 @@ 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
OpenPOWER on IntegriCloud