Skip to content
4 changes: 3 additions & 1 deletion clang/lib/CodeGen/CGCXXABI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,9 @@ bool CGCXXABI::isZeroInitializable(const MemberPointerType *MPT) {
return true;
}

void CGCXXABI::buildThisParam(CodeGenFunction &CGF, FunctionArgList &params, const CXXMethodDecl* MD) {
void CGCXXABI::buildThisParam(CodeGenFunction &CGF, FunctionArgList &params) {
const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl());

// FIXME: I'm not entirely sure I like using a fake decl just for code
// generation. Maybe we can come up with a better way?
auto *ThisDecl = ImplicitParamDecl::Create(
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/CGCXXABI.h
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,7 @@ class CGCXXABI {
}

/// Build a parameter variable suitable for 'this'.
void buildThisParam(CodeGenFunction &CGF, FunctionArgList &Params, const CXXMethodDecl* MD);
void buildThisParam(CodeGenFunction &CGF, FunctionArgList &Params);

/// Insert any ABI-specific implicit parameters into the parameter list for a
/// function. This generally involves extra data for constructors and
Expand Down
201 changes: 112 additions & 89 deletions clang/lib/CodeGen/CGExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1914,14 +1914,20 @@ namespace {
/// that normally happen during l-value emission.
struct ConstantLValue {
llvm::Constant *Value;
llvm::Type *ElementTy;
bool HasOffsetApplied;

/*implicit*/ ConstantLValue(llvm::Constant *value,
bool hasOffsetApplied = false)
: Value(value), HasOffsetApplied(hasOffsetApplied) {}
: Value(value), ElementTy(nullptr), HasOffsetApplied(hasOffsetApplied) {}

/*implicit*/ ConstantLValue(llvm::Constant *value,
llvm::Type *elementTy,
bool hasOffsetApplied = false)
: Value(value), ElementTy(elementTy), HasOffsetApplied(hasOffsetApplied) {}

/*implicit*/ ConstantLValue(ConstantAddress address)
: ConstantLValue(address.getPointer()) {}
: ConstantLValue(address.getPointer(), address.getElementType()) {}
};

/// A helper class for emitting constant l-values.
Expand Down Expand Up @@ -1961,6 +1967,12 @@ class ConstantLValueEmitter : public ConstStmtVisitor<ConstantLValueEmitter,
ConstantLValue VisitMaterializeTemporaryExpr(
const MaterializeTemporaryExpr *E);

llvm::Type *ConvertBlockType(QualType Ty) {
if (CGM.getLangOpts().OpenCL)
return CGM.getGenericBlockLiteralType();
return CGM.getTypes().ConvertType(Ty);
}

bool hasNonZeroOffset() const {
return !Value.getLValueOffset().isZero();
}
Expand All @@ -1972,12 +1984,17 @@ class ConstantLValueEmitter : public ConstStmtVisitor<ConstantLValueEmitter,
}

/// Apply the value offset to the given constant.
llvm::Constant *applyOffset(llvm::Constant *C) {
llvm::Constant *applyOffset(llvm::Constant *C, llvm::Type *BaseElementTy) {
uint64_t OffsetVal = Value.getLValueOffset().getQuantity();

llvm::SmallVector<llvm::Constant*, 4> Indexes;
Indexes.push_back(llvm::ConstantInt::get(CGM.Int32Ty, 0));
llvm::Type* DestTy = CGM.getTypes().ConvertTypeForMem(DestType);
llvm::Type* DestElemTy = nullptr;
if (isa<BlockPointerType>(DestType.getCanonicalType().getTypePtr()))
DestElemTy = ConvertBlockType(DestType->getPointeeType());
else if (DestTy->isPointerTy())
DestElemTy = CGM.getTypes().ConvertTypeForMem(DestType->getPointeeType());
QualType CurType;
const APValue::LValueBase &base = Value.getLValueBase();
if (const ValueDecl *D = base.dyn_cast<const ValueDecl*>())
Expand All @@ -1987,101 +2004,107 @@ class ConstantLValueEmitter : public ConstStmtVisitor<ConstantLValueEmitter,
else
CurType = base.getTypeInfoType();

llvm::Type* CurrentType = BaseElementTy;

llvm::Type* CurrentType = nullptr;
if (!C->getType()->isOpaquePointerTy())
CurrentType = C->getType()->getPointerElementType();
llvm::Type* CElementType = CurrentType;

if(Value.hasLValuePath() && CGM.getTypes().ConvertTypeForMem(CurType) == CurrentType) {
ArrayRef<APValue::LValuePathEntry> Path = Value.getLValuePath();
for (unsigned I = 0; I != Path.size(); ++I) {
if (const RecordType* CurClass = CurType->getAs<RecordType>()) {
const Decl *BaseOrMember = Path[I].getAsBaseOrMember().getPointer();
if (const CXXRecordDecl *Base = dyn_cast<CXXRecordDecl>(BaseOrMember)) {
CurType = CGM.getContext().getRecordType(Base);
const CGRecordLayout &cgLayout = CGM.getTypes().getCGRecordLayout(CurClass->getDecl());
const ASTRecordLayout &astLayout = CGM.getContext().getASTRecordLayout(CurClass->getDecl());
CharUnits Offset = astLayout.getBaseClassOffset(Base);
if(Base->isEmpty() || Offset.isZero())
continue;
Indexes.push_back(llvm::ConstantInt::get(CGM.Int32Ty, cgLayout.getNonVirtualBaseLLVMFieldNo(Base)));
} else {
const FieldDecl *FD = cast<FieldDecl>(BaseOrMember);
CurType = FD->getType();
if (CurClass->isUnionType()) {
// Apply a bitcast, on unions it is safe
C = llvm::ConstantExpr::getGetElementPtr(CElementType, C, Indexes);
C = llvm::ConstantExpr::getBitCast(C, CGM.getTypes().ConvertTypeForMem(CurType)->getPointerTo());
CElementType = CGM.getTypes().ConvertTypeForMem(CurType);

Indexes.clear();
continue;
}
const CGRecordLayout &cgLayout = CGM.getTypes().getCGRecordLayout(CurClass->getDecl());
if (!cgLayout.hasLLVMFieldNo(FD)) {
break;
}
int32_t fieldIndex = cgLayout.getLLVMFieldNo(FD);
if(fieldIndex == -1) {
// Collapsed struct
CElementType = CGM.getTypes().ConvertTypeForMem(CurType);
C = llvm::ConstantExpr::getBitCast(C, CElementType->getPointerTo());
continue;
if (!CurrentType)
CurrentType = CGM.getTypes().ConvertTypeForMem(CurType);

if (C->getType()->isOpaquePointerTy())
CurrentType = nullptr;
else
assert(CurrentType == C->getType()->getNonOpaquePointerElementType());

llvm::Type* CElementType = CurrentType;

if(Value.hasLValuePath() && CGM.getTypes().ConvertTypeForMem(CurType) == CurrentType) {
ArrayRef<APValue::LValuePathEntry> Path = Value.getLValuePath();
for (unsigned I = 0; I != Path.size(); ++I) {
if (const RecordType* CurClass = CurType->getAs<RecordType>()) {
const Decl *BaseOrMember = Path[I].getAsBaseOrMember().getPointer();
if (const CXXRecordDecl *Base = dyn_cast<CXXRecordDecl>(BaseOrMember)) {
CurType = CGM.getContext().getRecordType(Base);
const CGRecordLayout &cgLayout = CGM.getTypes().getCGRecordLayout(CurClass->getDecl());
const ASTRecordLayout &astLayout = CGM.getContext().getASTRecordLayout(CurClass->getDecl());
CharUnits Offset = astLayout.getBaseClassOffset(Base);
if(Base->isEmpty() || Offset.isZero())
continue;
Indexes.push_back(llvm::ConstantInt::get(CGM.Int32Ty, cgLayout.getNonVirtualBaseLLVMFieldNo(Base)));
} else {
const FieldDecl *FD = cast<FieldDecl>(BaseOrMember);
CurType = FD->getType();
if (CurClass->isUnionType()) {
// Apply a bitcast, on unions it is safe
C = llvm::ConstantExpr::getGetElementPtr(CElementType, C, Indexes);
C = llvm::ConstantExpr::getBitCast(C, CGM.getTypes().ConvertTypeForMem(CurType)->getPointerTo());
CElementType = CGM.getTypes().ConvertTypeForMem(CurType);

Indexes.clear();
continue;
}
const CGRecordLayout &cgLayout = CGM.getTypes().getCGRecordLayout(CurClass->getDecl());
if (!cgLayout.hasLLVMFieldNo(FD)) {
break;
}
int32_t fieldIndex = cgLayout.getLLVMFieldNo(FD);
if(fieldIndex == -1) {
// Collapsed struct
CElementType = CGM.getTypes().ConvertTypeForMem(CurType);
C = llvm::ConstantExpr::getBitCast(C, CElementType->getPointerTo());
continue;
}
Indexes.push_back(llvm::ConstantInt::get(CGM.Int32Ty, fieldIndex));
}
Indexes.push_back(llvm::ConstantInt::get(CGM.Int32Ty, fieldIndex));
} else {
Indexes.push_back(llvm::ConstantInt::get(CGM.Int32Ty, Path[I].getAsArrayIndex()));
CurType = CGM.getContext().getAsArrayType(CurType)->getElementType();
}
} else {
Indexes.push_back(llvm::ConstantInt::get(CGM.Int32Ty, Path[I].getAsArrayIndex()));
CurType = CGM.getContext().getAsArrayType(CurType)->getElementType();
}
}
if (Value.isLValueOnePastTheEnd()) {
Indexes.back() = llvm::ConstantInt::get(CGM.Int32Ty, cast<llvm::ConstantInt>(Indexes.back())->getZExtValue()+1);
}
OffsetVal = 0;
} else if (CurrentType) {
// Try to build a naturally looking GEP from the returned expression to the
// required type
while(DestTy->isPointerTy() && (OffsetVal || CurrentType!=DestTy->getPointerElementType()))
{
if (llvm::StructType* ST=dyn_cast<llvm::StructType>(CurrentType))
if (Value.isLValueOnePastTheEnd()) {
Indexes.back() = llvm::ConstantInt::get(CGM.Int32Ty, cast<llvm::ConstantInt>(Indexes.back())->getZExtValue()+1);
}
OffsetVal = 0;
} else if (CurrentType) {
// Try to build a naturally looking GEP from the returned expression to the
// required type
while(DestTy->isPointerTy() && (OffsetVal || CurrentType!=DestElemTy))
{
if (ST->isOpaque())
break;
if(!OffsetVal)
if (llvm::StructType* ST=dyn_cast<llvm::StructType>(CurrentType))
{
llvm::StructType* curBase = ST;
bool isBaseGood = false;
while((curBase = curBase->getDirectBase()))
if (ST->isOpaque())
break;
if(!OffsetVal)
{
if(curBase == DestTy->getPointerElementType())
llvm::StructType* curBase = ST;
bool isBaseGood = false;
while((curBase = curBase->getDirectBase()))
{
isBaseGood = true;
break;
if(curBase == DestElemTy)
{
isBaseGood = true;
break;
}
}
if(isBaseGood)
break;
}
if(isBaseGood)
break;
const llvm::StructLayout *SL = CGM.getDataLayout().getStructLayout(ST);
unsigned Index = SL->getElementContainingOffset(OffsetVal);
Indexes.push_back(llvm::ConstantInt::get(CGM.Int32Ty, Index));
OffsetVal -= SL->getElementOffset(Index);
CurrentType = ST->getElementType(Index);
}
const llvm::StructLayout *SL = CGM.getDataLayout().getStructLayout(ST);
unsigned Index = SL->getElementContainingOffset(OffsetVal);
Indexes.push_back(llvm::ConstantInt::get(CGM.Int32Ty, Index));
OffsetVal -= SL->getElementOffset(Index);
CurrentType = ST->getElementType(Index);
}
else if (llvm::ArrayType* AT=dyn_cast<llvm::ArrayType>(CurrentType))
{
llvm::Type *ElementTy = AT->getElementType();
unsigned ElementSize = CGM.getDataLayout().getTypeAllocSize(ElementTy);
unsigned Index = OffsetVal / ElementSize;
Indexes.push_back(llvm::ConstantInt::get(CGM.Int32Ty, Index));
OffsetVal -= Index * ElementSize;
CurrentType = ElementTy;
else if (llvm::ArrayType* AT=dyn_cast<llvm::ArrayType>(CurrentType))
{
llvm::Type *ElementTy = AT->getElementType();
unsigned ElementSize = CGM.getDataLayout().getTypeAllocSize(ElementTy);
unsigned Index = OffsetVal / ElementSize;
Indexes.push_back(llvm::ConstantInt::get(CGM.Int32Ty, Index));
OffsetVal -= Index * ElementSize;
CurrentType = ElementTy;
}
else
break;
}
else
break;
}
}

if(Indexes.size() > 1)
Expand Down Expand Up @@ -2129,7 +2152,7 @@ llvm::Constant *ConstantLValueEmitter::tryEmit() {

// Apply the offset if necessary and not already done.
if (!result.HasOffsetApplied) {
value = applyOffset(value);
value = applyOffset(value, result.ElementTy);
}

// Convert to the appropriate type; this could be an lvalue for
Expand Down Expand Up @@ -2276,7 +2299,7 @@ ConstantLValueEmitter::VisitAddrLabelExpr(const AddrLabelExpr *E) {
llvm::Constant *Ptr = Emitter.CGF->GetAddrOfLabel(E->getLabel());
Ptr = llvm::ConstantExpr::getBitCast(Ptr,
CGM.getTypes().ConvertType(E->getType()));
return Ptr;
return ConstantLValue(Ptr, CGM.getTypes().ConvertTypeForMem(E->getType()->getPointeeType()));
}

ConstantLValue
Expand Down Expand Up @@ -2306,7 +2329,7 @@ ConstantLValueEmitter::VisitBlockExpr(const BlockExpr *E) {
else
functionName = "global";

return CGM.GetAddrOfGlobalBlock(E, functionName);
return ConstantLValue(CGM.GetAddrOfGlobalBlock(E, functionName), ConvertBlockType(E->getType()->getPointeeType()));
}

ConstantLValue
Expand Down
21 changes: 16 additions & 5 deletions clang/lib/CodeGen/CGExprScalar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2194,15 +2194,15 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
}

bool asmjs = CGF.CurFn && CGF.CurFn->getSection() == StringRef("asmjs");
bool srcIsFunc = E->getType()->isFunctionPointerType();
bool dstIsFunc = DestTy->isFunctionPointerType();
//We don't care about casts to functions types
if (SrcTy->isVectorTy() || DstTy->isVectorTy() || CGF.getTarget().isByteAddressable() || isa<llvm::ConstantPointerNull>(Src) ||
(isa<llvm::FunctionType>(SrcTy->getPointerElementType()) && isa<llvm::FunctionType>(DstTy->getPointerElementType())) ||
DstTy == SrcTy || asmjs)
(srcIsFunc && dstIsFunc) || DstTy == SrcTy || asmjs)
{
// See below
}
else if (isa<llvm::FunctionType>(SrcTy->getPointerElementType()) &&
!isa<llvm::FunctionType>(DstTy->getPointerElementType()))
else if (srcIsFunc && !dstIsFunc)
{
if (!asmjs)
{
Expand All @@ -2214,7 +2214,8 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
{
llvm::Function* intrinsic = CGF.CGM.GetUserCastIntrinsic(CE, E->getType(), DestTy, asmjs);
llvm::CallBase* CB = Builder.CreateCall(intrinsic, Src);
CB->addParamAttr(0, llvm::Attribute::get(CB->getContext(), llvm::Attribute::ElementType, Src->getType()->getPointerElementType()));
llvm::Type* SrcPointeeTy = ConvertType(E->getType()->getPointeeType());
CB->addParamAttr(0, llvm::Attribute::get(CB->getContext(), llvm::Attribute::ElementType, SrcPointeeTy));
return CB;
}
return Builder.CreateBitCast(Src, DstTy);
Expand All @@ -2231,6 +2232,16 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
return CGF.CGM.getNullPointer(cast<llvm::PointerType>(
ConvertType(DestTy)), DestTy);
}

bool asmjs = CGF.CurFn && CGF.CurFn->getSection() == StringRef("asmjs");
bool srcIsFunc = E->getType()->isFunctionPointerType();
bool dstIsFunc = DestTy->isFunctionPointerType();
if (srcIsFunc && !dstIsFunc && !asmjs)
{
// On Cheerp in generic code we can't allow any function pointer to become any other pointer
CGF.CGM.getDiags().Report(CE->getBeginLoc(), diag::err_cheerp_bad_function_to_non_function_cast);
}

// 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.CGM.getTargetCodeGenInfo().performAddrSpaceCast(
Expand Down
Loading
Loading