forked from OSchip/llvm-project
parent
266ee4a5b3
commit
65511704f7
clang/lib/CodeGen
|
@ -388,7 +388,8 @@ llvm::Value * CodeGenFunction::EmitCXXTypeidExpr(const CXXTypeidExpr *E) {
|
||||||
const llvm::FunctionType *FTy;
|
const llvm::FunctionType *FTy;
|
||||||
FTy = llvm::FunctionType::get(ResultType, false);
|
FTy = llvm::FunctionType::get(ResultType, false);
|
||||||
llvm::Value *F = CGM.CreateRuntimeFunction(FTy, "__cxa_bad_typeid");
|
llvm::Value *F = CGM.CreateRuntimeFunction(FTy, "__cxa_bad_typeid");
|
||||||
Builder.CreateCall(F);
|
Builder.CreateCall(F)->setDoesNotReturn();
|
||||||
|
// FIXME: Should we have the below?
|
||||||
Builder.CreateUnreachable();
|
Builder.CreateUnreachable();
|
||||||
EmitBlock(NonZeroBlock);
|
EmitBlock(NonZeroBlock);
|
||||||
}
|
}
|
||||||
|
@ -403,3 +404,111 @@ llvm::Value * CodeGenFunction::EmitCXXTypeidExpr(const CXXTypeidExpr *E) {
|
||||||
ErrorUnsupported(E, "typeid expression");
|
ErrorUnsupported(E, "typeid expression");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
llvm::Value *CodeGenFunction::EmitDynamicCast(llvm::Value *V,
|
||||||
|
const CXXDynamicCastExpr *DCE) {
|
||||||
|
QualType CastTy = DCE->getTypeAsWritten();
|
||||||
|
QualType ArgTy = DCE->getSubExpr()->getType();
|
||||||
|
const llvm::Type *LArgTy = ConvertType(ArgTy);
|
||||||
|
const llvm::Type *LTy = ConvertType(DCE->getType());
|
||||||
|
CXXRecordDecl *SrcTy;
|
||||||
|
CXXRecordDecl *DstTy;
|
||||||
|
QualType Ty = CastTy.getTypePtr()->getPointeeType();
|
||||||
|
CanQualType CanTy = CGM.getContext().getCanonicalType(Ty);
|
||||||
|
Ty = CanTy.getUnqualifiedType();
|
||||||
|
DstTy = cast<CXXRecordDecl>(Ty->getAs<RecordType>()->getDecl());
|
||||||
|
Ty = ArgTy;
|
||||||
|
if (ArgTy.getTypePtr()->isPointerType()
|
||||||
|
|| ArgTy.getTypePtr()->isReferenceType())
|
||||||
|
Ty = Ty.getTypePtr()->getPointeeType();
|
||||||
|
CanTy = CGM.getContext().getCanonicalType(Ty);
|
||||||
|
Ty = CanTy.getUnqualifiedType();
|
||||||
|
SrcTy = cast<CXXRecordDecl>(Ty->getAs<RecordType>()->getDecl());
|
||||||
|
bool CanBeZero = false;
|
||||||
|
bool ThrowOnBad = false;
|
||||||
|
bool ToVoid = false;
|
||||||
|
QualType InnerType = CastTy->getPointeeType();
|
||||||
|
if (CastTy->isPointerType()) {
|
||||||
|
// FIXME: if PointerType->hasAttr<NonNullAttr>(), we don't set this
|
||||||
|
CanBeZero = true;
|
||||||
|
if (InnerType->isVoidType())
|
||||||
|
ToVoid = true;
|
||||||
|
} else {
|
||||||
|
LTy = LTy->getPointerTo();
|
||||||
|
ThrowOnBad = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: Add support for ToVoid
|
||||||
|
|
||||||
|
// FIXME: Ensure non-runtime casts are done before this point.
|
||||||
|
|
||||||
|
llvm::BasicBlock *ContBlock = createBasicBlock();
|
||||||
|
llvm::BasicBlock *NullBlock = 0;
|
||||||
|
llvm::BasicBlock *NonZeroBlock = 0;
|
||||||
|
if (CanBeZero) {
|
||||||
|
NonZeroBlock = createBasicBlock();
|
||||||
|
NullBlock = createBasicBlock();
|
||||||
|
llvm::Value *Zero = llvm::Constant::getNullValue(LArgTy);
|
||||||
|
Builder.CreateCondBr(Builder.CreateICmpNE(V, Zero),
|
||||||
|
NonZeroBlock, NullBlock);
|
||||||
|
EmitBlock(NonZeroBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Call __dynamic_cast
|
||||||
|
const llvm::Type *ResultType = llvm::Type::getInt8PtrTy(VMContext);
|
||||||
|
const llvm::FunctionType *FTy;
|
||||||
|
std::vector<const llvm::Type*> ArgTys;
|
||||||
|
const llvm::Type *PtrToInt8Ty
|
||||||
|
= llvm::Type::getInt8Ty(VMContext)->getPointerTo();
|
||||||
|
const llvm::Type *PtrDiffTy = ConvertType(getContext().getSizeType());
|
||||||
|
ArgTys.push_back(PtrToInt8Ty);
|
||||||
|
ArgTys.push_back(PtrToInt8Ty);
|
||||||
|
ArgTys.push_back(PtrToInt8Ty);
|
||||||
|
ArgTys.push_back(PtrDiffTy);
|
||||||
|
FTy = llvm::FunctionType::get(ResultType, ArgTys, false);
|
||||||
|
|
||||||
|
// FIXME: Calculate better hint.
|
||||||
|
llvm::Value *hint = llvm::ConstantInt::get(PtrDiffTy, -1ULL);
|
||||||
|
llvm::Value *SrcArg = CGM.GenerateRttiRef(SrcTy);
|
||||||
|
llvm::Value *DstArg = CGM.GenerateRttiRef(DstTy);
|
||||||
|
V = Builder.CreateBitCast(V, PtrToInt8Ty);
|
||||||
|
V = Builder.CreateCall4(CGM.CreateRuntimeFunction(FTy, "__dynamic_cast"),
|
||||||
|
V, SrcArg, DstArg, hint);
|
||||||
|
V = Builder.CreateBitCast(V, LTy);
|
||||||
|
|
||||||
|
llvm::BasicBlock *BadCastBlock = 0;
|
||||||
|
if (ThrowOnBad) {
|
||||||
|
BadCastBlock = createBasicBlock();
|
||||||
|
|
||||||
|
llvm::Value *Zero = llvm::Constant::getNullValue(LTy);
|
||||||
|
Builder.CreateCondBr(Builder.CreateICmpNE(V, Zero),
|
||||||
|
ContBlock, BadCastBlock);
|
||||||
|
EmitBlock(BadCastBlock);
|
||||||
|
/// Call __cxa_bad_cast
|
||||||
|
ResultType = llvm::Type::getVoidTy(VMContext);
|
||||||
|
const llvm::FunctionType *FBadTy;
|
||||||
|
FTy = llvm::FunctionType::get(ResultType, false);
|
||||||
|
llvm::Value *F = CGM.CreateRuntimeFunction(FBadTy, "__cxa_bad_cast");
|
||||||
|
Builder.CreateCall(F)->setDoesNotReturn();
|
||||||
|
// Builder.CreateUnreachable();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CanBeZero) {
|
||||||
|
Builder.CreateBr(ContBlock);
|
||||||
|
EmitBlock(NullBlock);
|
||||||
|
Builder.CreateBr(ContBlock);
|
||||||
|
}
|
||||||
|
EmitBlock(ContBlock);
|
||||||
|
if (CanBeZero) {
|
||||||
|
llvm::PHINode *PHI = Builder.CreatePHI(LTy);
|
||||||
|
PHI->reserveOperandSpace(3);
|
||||||
|
PHI->addIncoming(V, NonZeroBlock);
|
||||||
|
PHI->addIncoming(llvm::Constant::getNullValue(LTy), NullBlock);
|
||||||
|
if (ThrowOnBad)
|
||||||
|
PHI->addIncoming(llvm::Constant::getNullValue(LTy), BadCastBlock);
|
||||||
|
V = PHI;
|
||||||
|
}
|
||||||
|
|
||||||
|
return V;
|
||||||
|
}
|
||||||
|
|
|
@ -1290,16 +1290,26 @@ CodeGenFunction::EmitConditionalOperatorLValue(const ConditionalOperator* E) {
|
||||||
return LValue::MakeAddr(Temp, MakeQualifiers(E->getType()));
|
return LValue::MakeAddr(Temp, MakeQualifiers(E->getType()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// EmitCastLValue - Casts are never lvalues. If a cast is needed by the code
|
/// EmitCastLValue - Casts are never lvalues unless that cast is a dynamic_cast.
|
||||||
/// generator in an lvalue context, then it must mean that we need the address
|
/// If the cast is a dynamic_cast, we can have the usual lvalue result,
|
||||||
/// of an aggregate in order to access one of its fields. This can happen for
|
/// otherwise if a cast is needed by the code generator in an lvalue context,
|
||||||
/// all the reasons that casts are permitted with aggregate result, including
|
/// then it must mean that we need the address of an aggregate in order to
|
||||||
/// noop aggregate casts, and cast from scalar to union.
|
/// access one of its fields. This can happen for all the reasons that casts
|
||||||
|
/// are permitted with aggregate result, including noop aggregate casts, and
|
||||||
|
/// cast from scalar to union.
|
||||||
LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
|
LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
|
||||||
switch (E->getCastKind()) {
|
switch (E->getCastKind()) {
|
||||||
default:
|
default:
|
||||||
return EmitUnsupportedLValue(E, "unexpected cast lvalue");
|
return EmitUnsupportedLValue(E, "unexpected cast lvalue");
|
||||||
|
|
||||||
|
case CastExpr::CK_Dynamic: {
|
||||||
|
LValue LV = EmitLValue(E->getSubExpr());
|
||||||
|
llvm::Value *V = LV.getAddress();
|
||||||
|
const CXXDynamicCastExpr *DCE = cast<CXXDynamicCastExpr>(E);
|
||||||
|
return LValue::MakeAddr(EmitDynamicCast(V, DCE),
|
||||||
|
MakeQualifiers(E->getType()));
|
||||||
|
}
|
||||||
|
|
||||||
case CastExpr::CK_NoOp:
|
case CastExpr::CK_NoOp:
|
||||||
case CastExpr::CK_ConstructorConversion:
|
case CastExpr::CK_ConstructorConversion:
|
||||||
case CastExpr::CK_UserDefinedConversion:
|
case CastExpr::CK_UserDefinedConversion:
|
||||||
|
|
|
@ -852,6 +852,12 @@ Value *ScalarExprEmitter::EmitCastExpr(const CastExpr *CE) {
|
||||||
Value *Src = Visit(const_cast<Expr*>(E));
|
Value *Src = Visit(const_cast<Expr*>(E));
|
||||||
return Builder.CreatePtrToInt(Src, ConvertType(DestTy));
|
return Builder.CreatePtrToInt(Src, ConvertType(DestTy));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case CastExpr::CK_Dynamic: {
|
||||||
|
Value *V = Visit(const_cast<Expr*>(E));
|
||||||
|
const CXXDynamicCastExpr *DCE = cast<CXXDynamicCastExpr>(CE);
|
||||||
|
return CGF.EmitDynamicCast(V, DCE);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -664,6 +664,7 @@ public:
|
||||||
void EmitCXXDeleteExpr(const CXXDeleteExpr *E);
|
void EmitCXXDeleteExpr(const CXXDeleteExpr *E);
|
||||||
|
|
||||||
llvm::Value* EmitCXXTypeidExpr(const CXXTypeidExpr *E);
|
llvm::Value* EmitCXXTypeidExpr(const CXXTypeidExpr *E);
|
||||||
|
llvm::Value *EmitDynamicCast(llvm::Value *V, const CXXDynamicCastExpr *DCE);
|
||||||
|
|
||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
// Declaration Emission
|
// Declaration Emission
|
||||||
|
|
Loading…
Reference in New Issue