Skip to content

Commit

Permalink
[OpenCL] Add generic AS to 'this' pointer
Browse files Browse the repository at this point in the history
Address spaces are cast into generic before invoking the constructor.

Added support for a trailing Qualifiers object in FunctionProtoType.

Differential Revision: https://reviews.llvm.org/D54862

llvm-svn: 348927
  • Loading branch information
mikael-nilsson-arm committed Dec 12, 2018
1 parent f6c898e commit 78de847
Show file tree
Hide file tree
Showing 40 changed files with 390 additions and 143 deletions.
2 changes: 1 addition & 1 deletion clang/include/clang/AST/CanonicalType.h
Expand Up @@ -510,7 +510,7 @@ struct CanProxyAdaptor<FunctionProtoType>
}

LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVariadic)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getTypeQuals)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getTypeQuals)

using param_type_iterator =
CanTypeIterator<FunctionProtoType::param_type_iterator>;
Expand Down
5 changes: 4 additions & 1 deletion clang/include/clang/AST/DeclCXX.h
Expand Up @@ -2182,7 +2182,10 @@ class CXXMethodDecl : public FunctionDecl {
/// 'this' type.
QualType getThisType(ASTContext &C) const;

unsigned getTypeQualifiers() const {
static QualType getThisType(const FunctionProtoType *FPT,
const CXXRecordDecl *Decl);

Qualifiers getTypeQualifiers() const {
return getType()->getAs<FunctionProtoType>()->getTypeQuals();
}

Expand Down
54 changes: 36 additions & 18 deletions clang/include/clang/AST/Type.h
Expand Up @@ -256,28 +256,24 @@ class Qualifiers {
}

bool hasConst() const { return Mask & Const; }
void setConst(bool flag) {
Mask = (Mask & ~Const) | (flag ? Const : 0);
}
bool hasOnlyConst() const { return Mask == Const; }
void removeConst() { Mask &= ~Const; }
void addConst() { Mask |= Const; }

bool hasVolatile() const { return Mask & Volatile; }
void setVolatile(bool flag) {
Mask = (Mask & ~Volatile) | (flag ? Volatile : 0);
}
bool hasOnlyVolatile() const { return Mask == Volatile; }
void removeVolatile() { Mask &= ~Volatile; }
void addVolatile() { Mask |= Volatile; }

bool hasRestrict() const { return Mask & Restrict; }
void setRestrict(bool flag) {
Mask = (Mask & ~Restrict) | (flag ? Restrict : 0);
}
bool hasOnlyRestrict() const { return Mask == Restrict; }
void removeRestrict() { Mask &= ~Restrict; }
void addRestrict() { Mask |= Restrict; }

bool hasCVRQualifiers() const { return getCVRQualifiers(); }
unsigned getCVRQualifiers() const { return Mask & CVRMask; }
unsigned getCVRUQualifiers() const { return Mask & (CVRMask | UMask); }

void setCVRQualifiers(unsigned mask) {
assert(!(mask & ~CVRMask) && "bitmask contains non-CVR bits");
Mask = (Mask & ~CVRMask) | mask;
Expand Down Expand Up @@ -1526,7 +1522,9 @@ class Type : public ExtQualsTypeCommonBase {
///
/// C++ 8.3.5p4: The return type, the parameter type list and the
/// cv-qualifier-seq, [...], are part of the function type.
unsigned TypeQuals : 4;
unsigned FastTypeQuals : Qualifiers::FastWidth;
/// Whether this function has extended Qualifiers.
unsigned HasExtQuals : 1;

/// The number of parameters this function has, not counting '...'.
/// According to [implimits] 8 bits should be enough here but this is
Expand Down Expand Up @@ -3611,7 +3609,9 @@ class FunctionType : public Type {
FunctionTypeBits.ExtInfo = Info.Bits;
}

unsigned getTypeQuals() const { return FunctionTypeBits.TypeQuals; }
Qualifiers getFastTypeQuals() const {
return Qualifiers::fromFastMask(FunctionTypeBits.FastTypeQuals);
}

public:
QualType getReturnType() const { return ResultType; }
Expand All @@ -3626,9 +3626,14 @@ class FunctionType : public Type {

CallingConv getCallConv() const { return getExtInfo().getCC(); }
ExtInfo getExtInfo() const { return ExtInfo(FunctionTypeBits.ExtInfo); }
bool isConst() const { return getTypeQuals() & Qualifiers::Const; }
bool isVolatile() const { return getTypeQuals() & Qualifiers::Volatile; }
bool isRestrict() const { return getTypeQuals() & Qualifiers::Restrict; }

static_assert((~Qualifiers::FastMask & Qualifiers::CVRMask) == 0,
"Const, volatile and restrict are assumed to be a subset of "
"the fast qualifiers.");

bool isConst() const { return getFastTypeQuals().hasConst(); }
bool isVolatile() const { return getFastTypeQuals().hasVolatile(); }
bool isRestrict() const { return getFastTypeQuals().hasRestrict(); }

/// Determine the type of an expression that calls a function of
/// this type.
Expand Down Expand Up @@ -3689,7 +3694,7 @@ class FunctionProtoType final
private llvm::TrailingObjects<
FunctionProtoType, QualType, FunctionType::FunctionTypeExtraBitfields,
FunctionType::ExceptionType, Expr *, FunctionDecl *,
FunctionType::ExtParameterInfo> {
FunctionType::ExtParameterInfo, Qualifiers> {
friend class ASTContext; // ASTContext creates these.
friend TrailingObjects;

Expand Down Expand Up @@ -3717,6 +3722,10 @@ class FunctionProtoType final
// an ExtParameterInfo for each of the parameters. Present if and
// only if hasExtParameterInfos() is true.
//
// * Optionally a Qualifiers object to represent extra qualifiers that can't
// be represented by FunctionTypeBitfields.FastTypeQuals. Present if and only
// if hasExtQualifiers() is true.
//
// The optional FunctionTypeExtraBitfields has to be before the data
// related to the exception specification since it contains the number
// of exception types.
Expand Down Expand Up @@ -3763,7 +3772,7 @@ class FunctionProtoType final
FunctionType::ExtInfo ExtInfo;
bool Variadic : 1;
bool HasTrailingReturn : 1;
unsigned char TypeQuals = 0;
Qualifiers TypeQuals;
RefQualifierKind RefQualifier = RQ_None;
ExceptionSpecInfo ExceptionSpec;
const ExtParameterInfo *ExtParameterInfos = nullptr;
Expand Down Expand Up @@ -3875,6 +3884,10 @@ class FunctionProtoType final
return hasExtraBitfields(getExceptionSpecType());
}

bool hasExtQualifiers() const {
return FunctionTypeBits.HasExtQuals;
}

public:
unsigned getNumParams() const { return FunctionTypeBits.NumParams; }

Expand All @@ -3893,7 +3906,7 @@ class FunctionProtoType final
EPI.Variadic = isVariadic();
EPI.HasTrailingReturn = hasTrailingReturn();
EPI.ExceptionSpec.Type = getExceptionSpecType();
EPI.TypeQuals = static_cast<unsigned char>(getTypeQuals());
EPI.TypeQuals = getTypeQuals();
EPI.RefQualifier = getRefQualifier();
if (EPI.ExceptionSpec.Type == EST_Dynamic) {
EPI.ExceptionSpec.Exceptions = exceptions();
Expand Down Expand Up @@ -4003,7 +4016,12 @@ class FunctionProtoType final
/// Whether this function prototype has a trailing return type.
bool hasTrailingReturn() const { return FunctionTypeBits.HasTrailingReturn; }

unsigned getTypeQuals() const { return FunctionType::getTypeQuals(); }
Qualifiers getTypeQuals() const {
if (hasExtQualifiers())
return *getTrailingObjects<Qualifiers>();
else
return getFastTypeQuals();
}

/// Retrieve the ref-qualifier associated with this function type.
RefQualifierKind getRefQualifier() const {
Expand Down
4 changes: 2 additions & 2 deletions clang/include/clang/Sema/Sema.h
Expand Up @@ -5115,7 +5115,7 @@ class Sema {
/// using the given declaration (which is either a class template or a
/// class) along with the given qualifiers.
/// along with the qualifiers placed on '*this'.
CXXThisScopeRAII(Sema &S, Decl *ContextDecl, unsigned CXXThisTypeQuals,
CXXThisScopeRAII(Sema &S, Decl *ContextDecl, Qualifiers CXXThisTypeQuals,
bool Enabled = true);

~CXXThisScopeRAII();
Expand Down Expand Up @@ -7752,7 +7752,7 @@ class Sema {
SourceLocation Loc,
DeclarationName Entity,
CXXRecordDecl *ThisContext,
unsigned ThisTypeQuals);
Qualifiers ThisTypeQuals);
void SubstExceptionSpec(FunctionDecl *New, const FunctionProtoType *Proto,
const MultiLevelTemplateArgumentList &Args);
bool SubstExceptionSpec(SourceLocation Loc,
Expand Down
5 changes: 3 additions & 2 deletions clang/lib/AST/ASTContext.cpp
Expand Up @@ -3768,10 +3768,11 @@ QualType ASTContext::getFunctionTypeInternal(
size_t Size = FunctionProtoType::totalSizeToAlloc<
QualType, FunctionType::FunctionTypeExtraBitfields,
FunctionType::ExceptionType, Expr *, FunctionDecl *,
FunctionProtoType::ExtParameterInfo>(
FunctionProtoType::ExtParameterInfo, Qualifiers>(
NumArgs, FunctionProtoType::hasExtraBitfields(EPI.ExceptionSpec.Type),
ESH.NumExceptionType, ESH.NumExprPtr, ESH.NumFunctionDeclPtr,
EPI.ExtParameterInfos ? NumArgs : 0);
EPI.ExtParameterInfos ? NumArgs : 0,
EPI.TypeQuals.hasNonFastQualifiers() ? 1 : 0);

auto *FTP = (FunctionProtoType *)Allocate(Size, TypeAlignment);
FunctionProtoType::ExtProtoInfo newEPI = EPI;
Expand Down
7 changes: 4 additions & 3 deletions clang/lib/AST/ASTDumper.cpp
Expand Up @@ -199,9 +199,10 @@ namespace {
void VisitFunctionProtoType(const FunctionProtoType *T) {
auto EPI = T->getExtProtoInfo();
if (EPI.HasTrailingReturn) OS << " trailing_return";
if (T->isConst()) OS << " const";
if (T->isVolatile()) OS << " volatile";
if (T->isRestrict()) OS << " restrict";

if (!T->getTypeQuals().empty())
OS << " " << T->getTypeQuals().getAsString();

switch (EPI.RefQualifier) {
case RQ_None: break;
case RQ_LValue: OS << " &"; break;
Expand Down
15 changes: 10 additions & 5 deletions clang/lib/AST/DeclCXX.cpp
Expand Up @@ -2173,19 +2173,24 @@ CXXMethodDecl::overridden_methods() const {
return getASTContext().overridden_methods(this);
}

QualType CXXMethodDecl::getThisType(const FunctionProtoType *FPT,
const CXXRecordDecl *Decl) {
ASTContext &C = Decl->getASTContext();
QualType ClassTy = C.getTypeDeclType(Decl);
ClassTy = C.getQualifiedType(ClassTy, FPT->getTypeQuals());
return C.getPointerType(ClassTy);
}

QualType CXXMethodDecl::getThisType(ASTContext &C) const {
// C++ 9.3.2p1: The type of this in a member function of a class X is X*.
// If the member function is declared const, the type of this is const X*,
// if the member function is declared volatile, the type of this is
// volatile X*, and if the member function is declared const volatile,
// the type of this is const volatile X*.

assert(isInstance() && "No 'this' for static methods!");

QualType ClassTy = C.getTypeDeclType(getParent());
ClassTy = C.getQualifiedType(ClassTy,
Qualifiers::fromCVRUMask(getTypeQualifiers()));
return C.getPointerType(ClassTy);
return CXXMethodDecl::getThisType(getType()->getAs<FunctionProtoType>(),
getParent());
}

bool CXXMethodDecl::hasInlineBody() const {
Expand Down
5 changes: 2 additions & 3 deletions clang/lib/AST/ItaniumMangle.cpp
Expand Up @@ -1503,8 +1503,7 @@ void CXXNameMangler::mangleNestedName(const NamedDecl *ND,

Out << 'N';
if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(ND)) {
Qualifiers MethodQuals =
Qualifiers::fromCVRUMask(Method->getTypeQualifiers());
Qualifiers MethodQuals = Method->getTypeQualifiers();
// We do not consider restrict a distinguishing attribute for overloading
// purposes so we must not mangle it.
MethodQuals.removeRestrict();
Expand Down Expand Up @@ -2725,7 +2724,7 @@ void CXXNameMangler::mangleType(const FunctionProtoType *T) {

// Mangle CV-qualifiers, if present. These are 'this' qualifiers,
// e.g. "const" in "int (A::*)() const".
mangleQualifiers(Qualifiers::fromCVRUMask(T->getTypeQuals()));
mangleQualifiers(T->getTypeQuals());

// Mangle instantiation-dependent exception-specification, if present,
// per cxx-abi-dev proposal on 2016-10-11.
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/MicrosoftMangle.cpp
Expand Up @@ -2093,7 +2093,7 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T,
// If this is a C++ instance method, mangle the CVR qualifiers for the
// this pointer.
if (HasThisQuals) {
Qualifiers Quals = Qualifiers::fromCVRUMask(Proto->getTypeQuals());
Qualifiers Quals = Proto->getTypeQuals();
manglePointerExtQualifiers(Quals, /*PointeeType=*/QualType());
mangleRefQualifier(Proto->getRefQualifier());
mangleQualifiers(Quals, /*IsMember=*/false);
Expand Down
16 changes: 11 additions & 5 deletions clang/lib/AST/Type.cpp
Expand Up @@ -2851,7 +2851,7 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params,
result->isInstantiationDependentType(),
result->isVariablyModifiedType(),
result->containsUnexpandedParameterPack(), epi.ExtInfo) {
FunctionTypeBits.TypeQuals = epi.TypeQuals;
FunctionTypeBits.FastTypeQuals = epi.TypeQuals.getFastQualifiers();
FunctionTypeBits.RefQualifier = epi.RefQualifier;
FunctionTypeBits.NumParams = params.size();
assert(getNumParams() == params.size() && "NumParams overflow!");
Expand Down Expand Up @@ -2950,6 +2950,13 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params,
for (unsigned i = 0; i != getNumParams(); ++i)
extParamInfos[i] = epi.ExtParameterInfos[i];
}

if (epi.TypeQuals.hasNonFastQualifiers()) {
FunctionTypeBits.HasExtQuals = 1;
*getTrailingObjects<Qualifiers>() = epi.TypeQuals;
} else {
FunctionTypeBits.HasExtQuals = 0;
}
}

bool FunctionProtoType::hasDependentExceptionSpec() const {
Expand Down Expand Up @@ -3041,14 +3048,13 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result,
// shortcut, use one AddInteger call instead of four for the next four
// fields.
assert(!(unsigned(epi.Variadic) & ~1) &&
!(unsigned(epi.TypeQuals) & ~255) &&
!(unsigned(epi.RefQualifier) & ~3) &&
!(unsigned(epi.ExceptionSpec.Type) & ~15) &&
"Values larger than expected.");
ID.AddInteger(unsigned(epi.Variadic) +
(epi.TypeQuals << 1) +
(epi.RefQualifier << 9) +
(epi.ExceptionSpec.Type << 11));
(epi.RefQualifier << 1) +
(epi.ExceptionSpec.Type << 3));
ID.Add(epi.TypeQuals);
if (epi.ExceptionSpec.Type == EST_Dynamic) {
for (QualType Ex : epi.ExceptionSpec.Exceptions)
ID.AddPointer(Ex.getAsOpaquePtr());
Expand Down
6 changes: 2 additions & 4 deletions clang/lib/AST/TypePrinter.cpp
Expand Up @@ -801,10 +801,8 @@ void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T,

printFunctionAfter(Info, OS);

if (unsigned quals = T->getTypeQuals()) {
OS << ' ';
AppendTypeQualList(OS, quals, Policy.Restrict);
}
if (!T->getTypeQuals().empty())
OS << " " << T->getTypeQuals().getAsString();

switch (T->getRefQualifier()) {
case RQ_None:
Expand Down
16 changes: 9 additions & 7 deletions clang/lib/CodeGen/CGCall.cpp
Expand Up @@ -68,11 +68,13 @@ unsigned CodeGenTypes::ClangCallConvToLLVMCallConv(CallingConv CC) {
}
}

/// Derives the 'this' type for codegen purposes, i.e. ignoring method
/// Derives the 'this' type for codegen purposes, i.e. ignoring method CVR
/// qualification.
/// FIXME: address space qualification?
static CanQualType GetThisType(ASTContext &Context, const CXXRecordDecl *RD) {
static CanQualType GetThisType(ASTContext &Context, const CXXRecordDecl *RD,
const CXXMethodDecl *MD) {
QualType RecTy = Context.getTagDeclType(RD)->getCanonicalTypeInternal();
if (MD)
RecTy = Context.getAddrSpaceQualType(RecTy, MD->getType().getAddressSpace());
return Context.getPointerType(CanQualType::CreateUnsafe(RecTy));
}

Expand Down Expand Up @@ -250,7 +252,7 @@ CodeGenTypes::arrangeCXXMethodType(const CXXRecordDecl *RD,

// Add the 'this' pointer.
if (RD)
argTypes.push_back(GetThisType(Context, RD));
argTypes.push_back(GetThisType(Context, RD, MD));
else
argTypes.push_back(Context.VoidPtrTy);

Expand Down Expand Up @@ -306,7 +308,7 @@ CodeGenTypes::arrangeCXXStructorDeclaration(const CXXMethodDecl *MD,

SmallVector<CanQualType, 16> argTypes;
SmallVector<FunctionProtoType::ExtParameterInfo, 16> paramInfos;
argTypes.push_back(GetThisType(Context, MD->getParent()));
argTypes.push_back(GetThisType(Context, MD->getParent(), MD));

bool PassParams = true;

Expand Down Expand Up @@ -533,7 +535,7 @@ const CGFunctionInfo &
CodeGenTypes::arrangeUnprototypedMustTailThunk(const CXXMethodDecl *MD) {
assert(MD->isVirtual() && "only methods have thunks");
CanQual<FunctionProtoType> FTP = GetFormalType(MD);
CanQualType ArgTys[] = { GetThisType(Context, MD->getParent()) };
CanQualType ArgTys[] = { GetThisType(Context, MD->getParent(), MD) };
return arrangeLLVMFunctionInfo(Context.VoidTy, /*instanceMethod=*/false,
/*chainCall=*/false, ArgTys,
FTP->getExtInfo(), {}, RequiredArgs(1));
Expand All @@ -547,7 +549,7 @@ CodeGenTypes::arrangeMSCtorClosure(const CXXConstructorDecl *CD,
CanQual<FunctionProtoType> FTP = GetFormalType(CD);
SmallVector<CanQualType, 2> ArgTys;
const CXXRecordDecl *RD = CD->getParent();
ArgTys.push_back(GetThisType(Context, RD));
ArgTys.push_back(GetThisType(Context, RD, CD));
if (CT == Ctor_CopyingClosure)
ArgTys.push_back(*FTP->param_type_begin());
if (RD->getNumVBases() > 0)
Expand Down
14 changes: 13 additions & 1 deletion clang/lib/CodeGen/CGClass.cpp
Expand Up @@ -16,6 +16,7 @@
#include "CGDebugInfo.h"
#include "CGRecordLayout.h"
#include "CodeGenFunction.h"
#include "TargetInfo.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/EvaluatedExprVisitor.h"
Expand Down Expand Up @@ -2012,8 +2013,19 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
bool NewPointerIsChecked) {
CallArgList Args;

LangAS SlotAS = E->getType().getAddressSpace();
QualType ThisType = D->getThisType(getContext());
LangAS ThisAS = ThisType.getTypePtr()->getPointeeType().getAddressSpace();
llvm::Value *ThisPtr = This.getPointer();
if (SlotAS != ThisAS) {
unsigned TargetThisAS = getContext().getTargetAddressSpace(ThisAS);
llvm::Type *NewType =
ThisPtr->getType()->getPointerElementType()->getPointerTo(TargetThisAS);
ThisPtr = getTargetHooks().performAddrSpaceCast(*this, This.getPointer(),
ThisAS, SlotAS, NewType);
}
// Push the this ptr.
Args.add(RValue::get(This.getPointer()), D->getThisType(getContext()));
Args.add(RValue::get(ThisPtr), D->getThisType(getContext()));

// If this is a trivial constructor, emit a memcpy now before we lose
// the alignment information on the argument.
Expand Down

0 comments on commit 78de847

Please sign in to comment.