blob: 603d9a6e7e84f61d81171d5737255c63e7fe2e39 [file] [log] [blame]
//===--- CGExprScalar.cpp - Emit LLVM Code for Scalar Exprs ---------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This contains code to emit Expr nodes with scalar LLVM types as LLVM code.
//
//===----------------------------------------------------------------------===//
#include "CGCXXABI.h"
#include "CGCleanup.h"
#include "CGDebugInfo.h"
#include "CGObjCRuntime.h"
#include "CGOpenMPRuntime.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
#include "ConstantEmitter.h"
#include "TargetInfo.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Basic/CodeGenOptions.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/APFixedPoint.h"
#include "llvm/ADT/Optional.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/FixedPointBuilder.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GetElementPtrTypeIterator.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/IntrinsicsPowerPC.h"
#include "llvm/IR/MatrixBuilder.h"
#include "llvm/IR/Module.h"
#include <cstdarg>
using namespace clang;
using namespace CodeGen;
using llvm::Value;
//===----------------------------------------------------------------------===//
// Scalar Expression Emitter
//===----------------------------------------------------------------------===//
namespace {
/// Determine whether the given binary operation may overflow.
/// Sets \p Result to the value of the operation for BO_Add, BO_Sub, BO_Mul,
/// and signed BO_{Div,Rem}. For these opcodes, and for unsigned BO_{Div,Rem},
/// the returned overflow check is precise. The returned value is 'true' for
/// all other opcodes, to be conservative.
bool mayHaveIntegerOverflow(llvm::ConstantInt *LHS, llvm::ConstantInt *RHS,
BinaryOperator::Opcode Opcode, bool Signed,
llvm::APInt &Result) {
// Assume overflow is possible, unless we can prove otherwise.
bool Overflow = true;
const auto &LHSAP = LHS->getValue();
const auto &RHSAP = RHS->getValue();
if (Opcode == BO_Add) {
if (Signed)
Result = LHSAP.sadd_ov(RHSAP, Overflow);
else
Result = LHSAP.uadd_ov(RHSAP, Overflow);
} else if (Opcode == BO_Sub) {
if (Signed)
Result = LHSAP.ssub_ov(RHSAP, Overflow);
else
Result = LHSAP.usub_ov(RHSAP, Overflow);
} else if (Opcode == BO_Mul) {
if (Signed)
Result = LHSAP.smul_ov(RHSAP, Overflow);
else
Result = LHSAP.umul_ov(RHSAP, Overflow);
} else if (Opcode == BO_Div || Opcode == BO_Rem) {
if (Signed && !RHS->isZero())
Result = LHSAP.sdiv_ov(RHSAP, Overflow);
else
return false;
}
return Overflow;
}
struct BinOpInfo {
Value *LHS;
Value *RHS;
QualType Ty; // Computation Type.
BinaryOperator::Opcode Opcode; // Opcode of BinOp to perform
FPOptions FPFeatures;
const Expr *E; // Entire expr, for error unsupported. May not be binop.
/// Check if the binop can result in integer overflow.
bool mayHaveIntegerOverflow() const {
// Without constant input, we can't rule out overflow.
auto *LHSCI = dyn_cast<llvm::ConstantInt>(LHS);
auto *RHSCI = dyn_cast<llvm::ConstantInt>(RHS);
if (!LHSCI || !RHSCI)
return true;
llvm::APInt Result;
return ::mayHaveIntegerOverflow(
LHSCI, RHSCI, Opcode, Ty->hasSignedIntegerRepresentation(), Result);
}
/// Check if the binop computes a division or a remainder.
bool isDivremOp() const {
return Opcode == BO_Div || Opcode == BO_Rem || Opcode == BO_DivAssign ||
Opcode == BO_RemAssign;
}
/// Check if the binop can result in an integer division by zero.
bool mayHaveIntegerDivisionByZero() const {
if (isDivremOp())
if (auto *CI = dyn_cast<llvm::ConstantInt>(RHS))
return CI->isZero();
return true;
}
/// Check if the binop can result in a float division by zero.
bool mayHaveFloatDivisionByZero() const {
if (isDivremOp())
if (auto *CFP = dyn_cast<llvm::ConstantFP>(RHS))
return CFP->isZero();
return true;
}
/// Check if at least one operand is a fixed point type. In such cases, this
/// operation did not follow usual arithmetic conversion and both operands
/// might not be of the same type.
bool isFixedPointOp() const {
// We cannot simply check the result type since comparison operations return
// an int.
if (const auto *BinOp = dyn_cast<BinaryOperator>(E)) {
QualType LHSType = BinOp->getLHS()->getType();
QualType RHSType = BinOp->getRHS()->getType();
return LHSType->isFixedPointType() || RHSType->isFixedPointType();
}
if (const auto *UnOp = dyn_cast<UnaryOperator>(E))
return UnOp->getSubExpr()->getType()->isFixedPointType();
return false;
}
};
static bool MustVisitNullValue(const Expr *E) {
// If a null pointer expression's type is the C++0x nullptr_t, then
// it's not necessarily a simple constant and it must be evaluated
// for its potential side effects.
return E->getType()->isNullPtrType();
}
/// If \p E is a widened promoted integer, get its base (unpromoted) type.
static llvm::Optional<QualType> getUnwidenedIntegerType(const ASTContext &Ctx,
const Expr *E) {
const Expr *Base = E->IgnoreImpCasts();
if (E == Base)
return llvm::None;
QualType BaseTy = Base->getType();
if (!BaseTy->isPromotableIntegerType() ||
Ctx.getTypeSize(BaseTy) >= Ctx.getTypeSize(E->getType()))
return llvm::None;
return BaseTy;
}
/// Check if \p E is a widened promoted integer.
static bool IsWidenedIntegerOp(const ASTContext &Ctx, const Expr *E) {
return getUnwidenedIntegerType(Ctx, E).hasValue();
}
/// Check if we can skip the overflow check for \p Op.
static bool CanElideOverflowCheck(const ASTContext &Ctx, const BinOpInfo &Op) {
assert((isa<UnaryOperator>(Op.E) || isa<BinaryOperator>(Op.E)) &&
"Expected a unary or binary operator");
// If the binop has constant inputs and we can prove there is no overflow,
// we can elide the overflow check.
if (!Op.mayHaveIntegerOverflow())
return true;
// If a unary op has a widened operand, the op cannot overflow.
if (const auto *UO = dyn_cast<UnaryOperator>(Op.E))
return !UO->canOverflow();
// We usually don't need overflow checks for binops with widened operands.
// Multiplication with promoted unsigned operands is a special case.
const auto *BO = cast<BinaryOperator>(Op.E);
auto OptionalLHSTy = getUnwidenedIntegerType(Ctx, BO->getLHS());
if (!OptionalLHSTy)
return false;
auto OptionalRHSTy = getUnwidenedIntegerType(Ctx, BO->getRHS());
if (!OptionalRHSTy)
return false;
QualType LHSTy = *OptionalLHSTy;
QualType RHSTy = *OptionalRHSTy;
// This is the simple case: binops without unsigned multiplication, and with
// widened operands. No overflow check is needed here.
if ((Op.Opcode != BO_Mul && Op.Opcode != BO_MulAssign) ||
!LHSTy->isUnsignedIntegerType() || !RHSTy->isUnsignedIntegerType())
return true;
// For unsigned multiplication the overflow check can be elided if either one
// of the unpromoted types are less than half the size of the promoted type.
unsigned PromotedSize = Ctx.getTypeSize(Op.E->getType());
return (2 * Ctx.getTypeSize(LHSTy)) < PromotedSize ||
(2 * Ctx.getTypeSize(RHSTy)) < PromotedSize;
}
class ScalarExprEmitter
: public StmtVisitor<ScalarExprEmitter, Value*> {
CodeGenFunction &CGF;
CGBuilderTy &Builder;
bool IgnoreResultAssign;
llvm::LLVMContext &VMContext;
public:
ScalarExprEmitter(CodeGenFunction &cgf, bool ira=false)
: CGF(cgf), Builder(CGF.Builder), IgnoreResultAssign(ira),
VMContext(cgf.getLLVMContext()) {
}
//===--------------------------------------------------------------------===//
// Utilities
//===--------------------------------------------------------------------===//
bool TestAndClearIgnoreResultAssign() {
bool I = IgnoreResultAssign;
IgnoreResultAssign = false;
return I;
}
llvm::Type *ConvertType(QualType T) { return CGF.ConvertType(T); }
LValue EmitLValue(const Expr *E) { return CGF.EmitLValue(E); }
LValue EmitCheckedLValue(const Expr *E, CodeGenFunction::TypeCheckKind TCK) {
return CGF.EmitCheckedLValue(E, TCK);
}
void EmitBinOpCheck(ArrayRef<std::pair<Value *, SanitizerMask>> Checks,
const BinOpInfo &Info);
Value *EmitLoadOfLValue(LValue LV, SourceLocation Loc) {
return CGF.EmitLoadOfLValue(LV, Loc).getScalarVal();
}
void EmitLValueAlignmentAssumption(const Expr *E, Value *V) {
const AlignValueAttr *AVAttr = nullptr;
if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
const ValueDecl *VD = DRE->getDecl();
if (VD->getType()->isReferenceType()) {
if (const auto *TTy =
dyn_cast<TypedefType>(VD->getType().getNonReferenceType()))
AVAttr = TTy->getDecl()->getAttr<AlignValueAttr>();
} else {
// Assumptions for function parameters are emitted at the start of the
// function, so there is no need to repeat that here,
// unless the alignment-assumption sanitizer is enabled,
// then we prefer the assumption over alignment attribute
// on IR function param.
if (isa<ParmVarDecl>(VD) && !CGF.SanOpts.has(SanitizerKind::Alignment))
return;
AVAttr = VD->getAttr<AlignValueAttr>();
}
}
if (!AVAttr)
if (const auto *TTy =
dyn_cast<TypedefType>(E->getType()))
AVAttr = TTy->getDecl()->getAttr<AlignValueAttr>();
if (!AVAttr)
return;
Value *AlignmentValue = CGF.EmitScalarExpr(AVAttr->getAlignment());
llvm::ConstantInt *AlignmentCI = cast<llvm::ConstantInt>(AlignmentValue);
CGF.emitAlignmentAssumption(V, E, AVAttr->getLocation(), AlignmentCI);
}
/// EmitLoadOfLValue - Given an expression with complex type that represents a
/// value l-value, this method emits the address of the l-value, then loads
/// and returns the result.
Value *EmitLoadOfLValue(const Expr *E) {
Value *V = EmitLoadOfLValue(EmitCheckedLValue(E, CodeGenFunction::TCK_Load),
E->getExprLoc());
EmitLValueAlignmentAssumption(E, V);
return V;
}
/// EmitConversionToBool - Convert the specified expression value to a
/// boolean (i1) truth value. This is equivalent to "Val != 0".
Value *EmitConversionToBool(Value *Src, QualType DstTy);
/// Emit a check that a conversion from a floating-point type does not
/// overflow.
void EmitFloatConversionCheck(Value *OrigSrc, QualType OrigSrcType,
Value *Src, QualType SrcType, QualType DstType,
llvm::Type *DstTy, SourceLocation Loc);
/// Known implicit conversion check kinds.
/// Keep in sync with the enum of the same name in ubsan_handlers.h
enum ImplicitConversionCheckKind : unsigned char {
ICCK_IntegerTruncation = 0, // Legacy, was only used by clang 7.
ICCK_UnsignedIntegerTruncation = 1,
ICCK_SignedIntegerTruncation = 2,
ICCK_IntegerSignChange = 3,
ICCK_SignedIntegerTruncationOrSignChange = 4,
};
/// Emit a check that an [implicit] truncation of an integer does not
/// discard any bits. It is not UB, so we use the value after truncation.
void EmitIntegerTruncationCheck(Value *Src, QualType SrcType, Value *Dst,
QualType DstType, SourceLocation Loc);
/// Emit a check that an [implicit] conversion of an integer does not change
/// the sign of the value. It is not UB, so we use the value after conversion.
/// NOTE: Src and Dst may be the exact same value! (point to the same thing)
void EmitIntegerSignChangeCheck(Value *Src, QualType SrcType, Value *Dst,
QualType DstType, SourceLocation Loc);
/// Emit a conversion from the specified type to the specified destination
/// type, both of which are LLVM scalar types.
struct ScalarConversionOpts {
bool TreatBooleanAsSigned;
bool EmitImplicitIntegerTruncationChecks;
bool EmitImplicitIntegerSignChangeChecks;
ScalarConversionOpts()
: TreatBooleanAsSigned(false),
EmitImplicitIntegerTruncationChecks(false),
EmitImplicitIntegerSignChangeChecks(false) {}
ScalarConversionOpts(clang::SanitizerSet SanOpts)
: TreatBooleanAsSigned(false),
EmitImplicitIntegerTruncationChecks(
SanOpts.hasOneOf(SanitizerKind::ImplicitIntegerTruncation)),
EmitImplicitIntegerSignChangeChecks(
SanOpts.has(SanitizerKind::ImplicitIntegerSignChange)) {}
};
Value *EmitScalarCast(Value *Src, QualType SrcType, QualType DstType,
llvm::Type *SrcTy, llvm::Type *DstTy,
ScalarConversionOpts Opts);
Value *
EmitScalarConversion(Value *Src, QualType SrcTy, QualType DstTy,
SourceLocation Loc,
ScalarConversionOpts Opts = ScalarConversionOpts());
/// Convert between either a fixed point and other fixed point or fixed point
/// and an integer.
Value *EmitFixedPointConversion(Value *Src, QualType SrcTy, QualType DstTy,
SourceLocation Loc);
/// Emit a conversion from the specified complex type to the specified
/// destination type, where the destination type is an LLVM scalar type.
Value *EmitComplexToScalarConversion(CodeGenFunction::ComplexPairTy Src,
QualType SrcTy, QualType DstTy,
SourceLocation Loc);
/// EmitNullValue - Emit a value that corresponds to null for the given type.
Value *EmitNullValue(QualType Ty);
/// EmitFloatToBoolConversion - Perform an FP to boolean conversion.
Value *EmitFloatToBoolConversion(Value *V) {
// Compare against 0.0 for fp scalars.
llvm::Value *Zero = llvm::Constant::getNullValue(V->getType());
return Builder.CreateFCmpUNE(V, Zero, "tobool");
}
/// EmitPointerToBoolConversion - Perform a pointer to boolean conversion.
Value *EmitPointerToBoolConversion(Value *V, QualType QT) {
Value *Zero = CGF.CGM.getNullPointer(cast<llvm::PointerType>(V->getType()), QT);
return Builder.CreateICmpNE(V, Zero, "tobool");
}
Value *EmitIntToBoolConversion(Value *V) {
// Because of the type rules of C, we often end up computing a
// logical value, then zero extending it to int, then wanting it
// as a logical value again. Optimize this common case.
if (llvm::ZExtInst *ZI = dyn_cast<llvm::ZExtInst>(V)) {
if (ZI->getOperand(0)->getType() == Builder.getInt1Ty()) {
Value *Result = ZI->getOperand(0);
// If there aren't any more uses, zap the instruction to save space.
// Note that there can be more uses, for example if this
// is the result of an assignment.
if (ZI->use_empty())
ZI->eraseFromParent();
return Result;
}
}
return Builder.CreateIsNotNull(V, "tobool");
}
//===--------------------------------------------------------------------===//
// Visitor Methods
//===--------------------------------------------------------------------===//
Value *Visit(Expr *E) {
ApplyDebugLocation DL(CGF, E);
return StmtVisitor<ScalarExprEmitter, Value*>::Visit(E);
}
Value *VisitStmt(Stmt *S) {
S->dump(llvm::errs(), CGF.getContext());
llvm_unreachable("Stmt can't have complex result type!");
}
Value *VisitExpr(Expr *S);
Value *VisitConstantExpr(ConstantExpr *E) {
if (Value *Result = ConstantEmitter(CGF).tryEmitConstantExpr(E)) {
if (E->isGLValue())
return CGF.Builder.CreateLoad(Address(
Result, CGF.getContext().getTypeAlignInChars(E->getType())));
return Result;
}
return Visit(E->getSubExpr());
}
Value *VisitParenExpr(ParenExpr *PE) {
return Visit(PE->getSubExpr());
}
Value *VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *E) {
return Visit(E->getReplacement());
}
Value *VisitGenericSelectionExpr(GenericSelectionExpr *GE) {
return Visit(GE->getResultExpr());
}
Value *VisitCoawaitExpr(CoawaitExpr *S) {
return CGF.EmitCoawaitExpr(*S).getScalarVal();
}
Value *VisitCoyieldExpr(CoyieldExpr *S) {
return CGF.EmitCoyieldExpr(*S).getScalarVal();
}
Value *VisitUnaryCoawait(const UnaryOperator *E) {
return Visit(E->getSubExpr());
}
// Leaves.
Value *VisitIntegerLiteral(const IntegerLiteral *E) {
return Builder.getInt(E->getValue());
}
Value *VisitFixedPointLiteral(const FixedPointLiteral *E) {
return Builder.getInt(E->getValue());
}
Value *VisitFloatingLiteral(const FloatingLiteral *E) {
return llvm::ConstantFP::get(VMContext, E->getValue());
}
Value *VisitCharacterLiteral(const CharacterLiteral *E) {
return llvm::ConstantInt::get(ConvertType(E->getType()), E->getValue());
}
Value *VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *E) {
return llvm::ConstantInt::get(ConvertType(E->getType()), E->getValue());
}
Value *VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E) {
return llvm::ConstantInt::get(ConvertType(E->getType()), E->getValue());
}
Value *VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *E) {
return EmitNullValue(E->getType());
}
Value *VisitGNUNullExpr(const GNUNullExpr *E) {
return EmitNullValue(E->getType());
}
Value *VisitOffsetOfExpr(OffsetOfExpr *E);
Value *VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *E);
Value *VisitAddrLabelExpr(const AddrLabelExpr *E) {
llvm::Value *V = CGF.GetAddrOfLabel(E->getLabel());
return Builder.CreateBitCast(V, ConvertType(E->getType()));
}
Value *VisitSizeOfPackExpr(SizeOfPackExpr *E) {
return llvm::ConstantInt::get(ConvertType(E->getType()),E->getPackLength());
}
Value *VisitPseudoObjectExpr(PseudoObjectExpr *E) {
return CGF.EmitPseudoObjectRValue(E).getScalarVal();
}
Value *VisitOpaqueValueExpr(OpaqueValueExpr *E) {
if (E->isGLValue())
return EmitLoadOfLValue(CGF.getOrCreateOpaqueLValueMapping(E),
E->getExprLoc());
// Otherwise, assume the mapping is the scalar directly.
return CGF.getOrCreateOpaqueRValueMapping(E).getScalarVal();
}
// l-values.
Value *VisitDeclRefExpr(DeclRefExpr *E) {
if (CodeGenFunction::ConstantEmission Constant = CGF.tryEmitAsConstant(E))
return CGF.emitScalarConstant(Constant, E);
return EmitLoadOfLValue(E);
}
Value *VisitObjCSelectorExpr(ObjCSelectorExpr *E) {
return CGF.EmitObjCSelectorExpr(E);
}
Value *VisitObjCProtocolExpr(ObjCProtocolExpr *E) {
return CGF.EmitObjCProtocolExpr(E);
}
Value *VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
return EmitLoadOfLValue(E);
}
Value *VisitObjCMessageExpr(ObjCMessageExpr *E) {
if (E->getMethodDecl() &&
E->getMethodDecl()->getReturnType()->isReferenceType())
return EmitLoadOfLValue(E);
return CGF.EmitObjCMessageExpr(E).getScalarVal();
}
Value *VisitObjCIsaExpr(ObjCIsaExpr *E) {
LValue LV = CGF.EmitObjCIsaExpr(E);
Value *V = CGF.EmitLoadOfLValue(LV, E->getExprLoc()).getScalarVal();
return V;
}
Value *VisitObjCAvailabilityCheckExpr(ObjCAvailabilityCheckExpr *E) {
VersionTuple Version = E->getVersion();
// If we're checking for a platform older than our minimum deployment
// target, we can fold the check away.
if (Version <= CGF.CGM.getTarget().getPlatformMinVersion())
return llvm::ConstantInt::get(Builder.getInt1Ty(), 1);
return CGF.EmitBuiltinAvailable(Version);
}
Value *VisitArraySubscriptExpr(ArraySubscriptExpr *E);
Value *VisitMatrixSubscriptExpr(MatrixSubscriptExpr *E);
Value *VisitShuffleVectorExpr(ShuffleVectorExpr *E);
Value *VisitConvertVectorExpr(ConvertVectorExpr *E);
Value *VisitMemberExpr(MemberExpr *E);
Value *VisitExtVectorElementExpr(Expr *E) { return EmitLoadOfLValue(E); }
Value *VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
// Strictly speaking, we shouldn't be calling EmitLoadOfLValue, which
// transitively calls EmitCompoundLiteralLValue, here in C++ since compound
// literals aren't l-values in C++. We do so simply because that's the
// cleanest way to handle compound literals in C++.
// See the discussion here: https://reviews.llvm.org/D64464
return EmitLoadOfLValue(E);
}
Value *VisitInitListExpr(InitListExpr *E);
Value *VisitArrayInitIndexExpr(ArrayInitIndexExpr *E) {
assert(CGF.getArrayInitIndex() &&
"ArrayInitIndexExpr not inside an ArrayInitLoopExpr?");
return CGF.getArrayInitIndex();
}
Value *VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) {
return EmitNullValue(E->getType());
}
Value *VisitExplicitCastExpr(ExplicitCastExpr *E) {
CGF.CGM.EmitExplicitCastExprType(E, &CGF);
return VisitCastExpr(E);
}
Value *VisitCastExpr(CastExpr *E);
Value *VisitCallExpr(const CallExpr *E) {
if (E->getCallReturnType(CGF.getContext())->isReferenceType())
return EmitLoadOfLValue(E);
Value *V = CGF.EmitCallExpr(E).getScalarVal();
EmitLValueAlignmentAssumption(E, V);
return V;
}
Value *VisitStmtExpr(const StmtExpr *E);
// Unary Operators.
Value *VisitUnaryPostDec(const UnaryOperator *E) {
LValue LV = EmitLValue(E->getSubExpr());
return EmitScalarPrePostIncDec(E, LV, false, false);
}
Value *VisitUnaryPostInc(const UnaryOperator *E) {
LValue LV = EmitLValue(E->getSubExpr());
return EmitScalarPrePostIncDec(E, LV, true, false);
}
Value *VisitUnaryPreDec(const UnaryOperator *E) {
LValue LV = EmitLValue(E->getSubExpr());
return EmitScalarPrePostIncDec(E, LV, false, true);
}
Value *VisitUnaryPreInc(const UnaryOperator *E) {
LValue LV = EmitLValue(E->getSubExpr());
return EmitScalarPrePostIncDec(E, LV, true, true);
}
llvm::Value *EmitIncDecConsiderOverflowBehavior(const UnaryOperator *E,
llvm::Value *InVal,
bool IsInc);
llvm::Value *EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
bool isInc, bool isPre);
Value *VisitUnaryAddrOf(const UnaryOperator *E) {
if (isa<MemberPointerType>(E->getType())) // never sugared
return CGF.CGM.getMemberPointerConstant(E);
return EmitLValue(E->getSubExpr()).getPointer(CGF);
}
Value *VisitUnaryDeref(const UnaryOperator *E) {
if (E->getType()->isVoidType())
return Visit(E->getSubExpr()); // the actual value should be unused
return EmitLoadOfLValue(E);
}
Value *VisitUnaryPlus(const UnaryOperator *E) {
// This differs from gcc, though, most likely due to a bug in gcc.
TestAndClearIgnoreResultAssign();
return Visit(E->getSubExpr());
}
Value *VisitUnaryMinus (const UnaryOperator *E);
Value *VisitUnaryNot (const UnaryOperator *E);
Value *VisitUnaryLNot (const UnaryOperator *E);
Value *VisitUnaryReal (const UnaryOperator *E);
Value *VisitUnaryImag (const UnaryOperator *E);
Value *VisitUnaryExtension(const UnaryOperator *E) {
return Visit(E->getSubExpr());
}
// C++
Value *VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *E) {
return EmitLoadOfLValue(E);
}
Value *VisitSourceLocExpr(SourceLocExpr *SLE) {
auto &Ctx = CGF.getContext();
APValue Evaluated =
SLE->EvaluateInContext(Ctx, CGF.CurSourceLocExprScope.getDefaultExpr());
return ConstantEmitter(CGF).emitAbstract(SLE->getLocation(), Evaluated,
SLE->getType());
}
Value *VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE) {
CodeGenFunction::CXXDefaultArgExprScope Scope(CGF, DAE);
return Visit(DAE->getExpr());
}
Value *VisitCXXDefaultInitExpr(CXXDefaultInitExpr *DIE) {
CodeGenFunction::CXXDefaultInitExprScope Scope(CGF, DIE);
return Visit(DIE->getExpr());
}
Value *VisitCXXThisExpr(CXXThisExpr *TE) {
return CGF.LoadCXXThis();
}
Value *VisitExprWithCleanups(ExprWithCleanups *E);
Value *VisitCXXNewExpr(const CXXNewExpr *E) {
return CGF.EmitCXXNewExpr(E);
}
Value *VisitCXXDeleteExpr(const CXXDeleteExpr *E) {
CGF.EmitCXXDeleteExpr(E);
return nullptr;
}
Value *VisitTypeTraitExpr(const TypeTraitExpr *E) {
return llvm::ConstantInt::get(ConvertType(E->getType()), E->getValue());
}
Value *VisitConceptSpecializationExpr(const ConceptSpecializationExpr *E) {
return Builder.getInt1(E->isSatisfied());
}
Value *VisitRequiresExpr(const RequiresExpr *E) {
return Builder.getInt1(E->isSatisfied());
}
Value *VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *E) {
return llvm::ConstantInt::get(Builder.getInt32Ty(), E->getValue());
}
Value *VisitExpressionTraitExpr(const ExpressionTraitExpr *E) {
return llvm::ConstantInt::get(Builder.getInt1Ty(), E->getValue());
}
Value *VisitCXXPseudoDestructorExpr(const CXXPseudoDestructorExpr *E) {
// C++ [expr.pseudo]p1:
// The result shall only be used as the operand for the function call
// operator (), and the result of such a call has type void. The only
// effect is the evaluation of the postfix-expression before the dot or
// arrow.
CGF.EmitScalarExpr(E->getBase());
return nullptr;
}
Value *VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E) {
return EmitNullValue(E->getType());
}
Value *VisitCXXThrowExpr(const CXXThrowExpr *E) {
CGF.EmitCXXThrowExpr(E);
return nullptr;
}
Value *VisitCXXNoexceptExpr(const CXXNoexceptExpr *E) {
return Builder.getInt1(E->getValue());
}
// Binary Operators.
Value *EmitMul(const BinOpInfo &Ops) {
if (Ops.Ty->isSignedIntegerOrEnumerationType()) {
switch (CGF.getLangOpts().getSignedOverflowBehavior()) {
case LangOptions::SOB_Defined:
return Builder.CreateMul(Ops.LHS, Ops.RHS, "mul");
case LangOptions::SOB_Undefined:
if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
return Builder.CreateNSWMul(Ops.LHS, Ops.RHS, "mul");
LLVM_FALLTHROUGH;
case LangOptions::SOB_Trapping:
if (CanElideOverflowCheck(CGF.getContext(), Ops))
return Builder.CreateNSWMul(Ops.LHS, Ops.RHS, "mul");
return EmitOverflowCheckedBinOp(Ops);
}
}
if (Ops.Ty->isConstantMatrixType()) {
llvm::MatrixBuilder<CGBuilderTy> MB(Builder);
// We need to check the types of the operands of the operator to get the
// correct matrix dimensions.
auto *BO = cast<BinaryOperator>(Ops.E);
auto *LHSMatTy = dyn_cast<ConstantMatrixType>(
BO->getLHS()->getType().getCanonicalType());
auto *RHSMatTy = dyn_cast<ConstantMatrixType>(
BO->getRHS()->getType().getCanonicalType());
if (LHSMatTy && RHSMatTy)
return MB.CreateMatrixMultiply(Ops.LHS, Ops.RHS, LHSMatTy->getNumRows(),
LHSMatTy->getNumColumns(),
RHSMatTy->getNumColumns());
return MB.CreateScalarMultiply(Ops.LHS, Ops.RHS);
}
if (Ops.Ty->isUnsignedIntegerType() &&
CGF.SanOpts.has(SanitizerKind::UnsignedIntegerOverflow) &&
!CanElideOverflowCheck(CGF.getContext(), Ops))
return EmitOverflowCheckedBinOp(Ops);
if (Ops.LHS->getType()->isFPOrFPVectorTy()) {
// Preserve the old values
CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, Ops.FPFeatures);
return Builder.CreateFMul(Ops.LHS, Ops.RHS, "mul");
}
if (Ops.isFixedPointOp())
return EmitFixedPointBinOp(Ops);
return Builder.CreateMul(Ops.LHS, Ops.RHS, "mul");
}
/// Create a binary op that checks for overflow.
/// Currently only supports +, - and *.
Value *EmitOverflowCheckedBinOp(const BinOpInfo &Ops);
// Check for undefined division and modulus behaviors.
void EmitUndefinedBehaviorIntegerDivAndRemCheck(const BinOpInfo &Ops,
llvm::Value *Zero,bool isDiv);
// Common helper for getting how wide LHS of shift is.
static Value *GetWidthMinusOneValue(Value* LHS,Value* RHS);
// Used for shifting constraints for OpenCL, do mask for powers of 2, URem for
// non powers of two.
Value *ConstrainShiftValue(Value *LHS, Value *RHS, const Twine &Name);
Value *EmitDiv(const BinOpInfo &Ops);
Value *EmitRem(const BinOpInfo &Ops);
Value *EmitAdd(const BinOpInfo &Ops);
Value *EmitSub(const BinOpInfo &Ops);
Value *EmitShl(const BinOpInfo &Ops);
Value *EmitShr(const BinOpInfo &Ops);
Value *EmitAnd(const BinOpInfo &Ops) {
return Builder.CreateAnd(Ops.LHS, Ops.RHS, "and");
}
Value *EmitXor(const BinOpInfo &Ops) {
return Builder.CreateXor(Ops.LHS, Ops.RHS, "xor");
}
Value *EmitOr (const BinOpInfo &Ops) {
return Builder.CreateOr(Ops.LHS, Ops.RHS, "or");
}
// Helper functions for fixed point binary operations.
Value *EmitFixedPointBinOp(const BinOpInfo &Ops);
BinOpInfo EmitBinOps(const BinaryOperator *E);
LValue EmitCompoundAssignLValue(const CompoundAssignOperator *E,
Value *(ScalarExprEmitter::*F)(const BinOpInfo &),
Value *&Result);
Value *EmitCompoundAssign(const CompoundAssignOperator *E,
Value *(ScalarExprEmitter::*F)(const BinOpInfo &));
// Binary operators and binary compound assignment operators.
#define HANDLEBINOP(OP) \
Value *VisitBin ## OP(const BinaryOperator *E) { \
return Emit ## OP(EmitBinOps(E)); \
} \
Value *VisitBin ## OP ## Assign(const CompoundAssignOperator *E) { \
return EmitCompoundAssign(E, &ScalarExprEmitter::Emit ## OP); \
}
HANDLEBINOP(Mul)
HANDLEBINOP(Div)
HANDLEBINOP(Rem)
HANDLEBINOP(Add)
HANDLEBINOP(Sub)
HANDLEBINOP(Shl)
HANDLEBINOP(Shr)
HANDLEBINOP(And)
HANDLEBINOP(Xor)
HANDLEBINOP(Or)
#undef HANDLEBINOP
// Comparisons.
Value *EmitCompare(const BinaryOperator *E, llvm::CmpInst::Predicate UICmpOpc,
llvm::CmpInst::Predicate SICmpOpc,
llvm::CmpInst::Predicate FCmpOpc, bool IsSignaling);
#define VISITCOMP(CODE, UI, SI, FP, SIG) \
Value *VisitBin##CODE(const BinaryOperator *E) { \
return EmitCompare(E, llvm::ICmpInst::UI, llvm::ICmpInst::SI, \
llvm::FCmpInst::FP, SIG); }
VISITCOMP(LT, ICMP_ULT, ICMP_SLT, FCMP_OLT, true)
VISITCOMP(GT, ICMP_UGT, ICMP_SGT, FCMP_OGT, true)
VISITCOMP(LE, ICMP_ULE, ICMP_SLE, FCMP_OLE, true)
VISITCOMP(GE, ICMP_UGE, ICMP_SGE, FCMP_OGE, true)
VISITCOMP(EQ, ICMP_EQ , ICMP_EQ , FCMP_OEQ, false)
VISITCOMP(NE, ICMP_NE , ICMP_NE , FCMP_UNE, false)
#undef VISITCOMP
Value *VisitBinAssign (const BinaryOperator *E);
Value *VisitBinLAnd (const BinaryOperator *E);
Value *VisitBinLOr (const BinaryOperator *E);
Value *VisitBinComma (const BinaryOperator *E);
Value *VisitBinPtrMemD(const Expr *E) { return EmitLoadOfLValue(E); }
Value *VisitBinPtrMemI(const Expr *E) { return EmitLoadOfLValue(E); }
Value *VisitCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator *E) {
return Visit(E->getSemanticForm());
}
// Other Operators.
Value *VisitBlockExpr(const BlockExpr *BE);
Value *VisitAbstractConditionalOperator(const AbstractConditionalOperator *);
Value *VisitChooseExpr(ChooseExpr *CE);
Value *VisitVAArgExpr(VAArgExpr *VE);
Value *VisitObjCStringLiteral(const ObjCStringLiteral *E) {
return CGF.EmitObjCStringLiteral(E);
}
Value *VisitObjCBoxedExpr(ObjCBoxedExpr *E) {
return CGF.EmitObjCBoxedExpr(E);
}
Value *VisitObjCArrayLiteral(ObjCArrayLiteral *E) {
return CGF.EmitObjCArrayLiteral(E);
}
Value *VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) {
return CGF.EmitObjCDictionaryLiteral(E);
}
Value *VisitAsTypeExpr(AsTypeExpr *CE);
Value *VisitAtomicExpr(AtomicExpr *AE);
};
} // end anonymous namespace.
//===----------------------------------------------------------------------===//
// Utilities
//===----------------------------------------------------------------------===//
/// EmitConversionToBool - Convert the specified expression value to a
/// boolean (i1) truth value. This is equivalent to "Val != 0".
Value *ScalarExprEmitter::EmitConversionToBool(Value *Src, QualType SrcType) {
assert(SrcType.isCanonical() && "EmitScalarConversion strips typedefs");
if (SrcType->isRealFloatingType())
return EmitFloatToBoolConversion(Src);
if (const MemberPointerType *MPT = dyn_cast<MemberPointerType>(SrcType))
return CGF.CGM.getCXXABI().EmitMemberPointerIsNotNull(CGF, Src, MPT);
assert((SrcType->isIntegerType() || isa<llvm::PointerType>(Src->getType())) &&
"Unknown scalar type to convert");
if (isa<llvm::IntegerType>(Src->getType()))
return EmitIntToBoolConversion(Src);
assert(isa<llvm::PointerType>(Src->getType()));
return EmitPointerToBoolConversion(Src, SrcType);
}
void ScalarExprEmitter::EmitFloatConversionCheck(
Value *OrigSrc, QualType OrigSrcType, Value *Src, QualType SrcType,
QualType DstType, llvm::Type *DstTy, SourceLocation Loc) {
assert(SrcType->isFloatingType() && "not a conversion from floating point");
if (!isa<llvm::IntegerType>(DstTy))
return;
CodeGenFunction::SanitizerScope SanScope(&CGF);
using llvm::APFloat;
using llvm::APSInt;
llvm::Value *Check = nullptr;
const llvm::fltSemantics &SrcSema =
CGF.getContext().getFloatTypeSemantics(OrigSrcType);
// Floating-point to integer. This has undefined behavior if the source is
// +-Inf, NaN, or doesn't fit into the destination type (after truncation
// to an integer).
unsigned Width = CGF.getContext().getIntWidth(DstType);
bool Unsigned = DstType->isUnsignedIntegerOrEnumerationType();
APSInt Min = APSInt::getMinValue(Width, Unsigned);
APFloat MinSrc(SrcSema, APFloat::uninitialized);
if (MinSrc.convertFromAPInt(Min, !Unsigned, APFloat::rmTowardZero) &
APFloat::opOverflow)
// Don't need an overflow check for lower bound. Just check for
// -Inf/NaN.
MinSrc = APFloat::getInf(SrcSema, true);
else
// Find the largest value which is too small to represent (before
// truncation toward zero).
MinSrc.subtract(APFloat(SrcSema, 1), APFloat::rmTowardNegative);
APSInt Max = APSInt::getMaxValue(Width, Unsigned);
APFloat MaxSrc(SrcSema, APFloat::uninitialized);
if (MaxSrc.convertFromAPInt(Max, !Unsigned, APFloat::rmTowardZero) &
APFloat::opOverflow)
// Don't need an overflow check for upper bound. Just check for
// +Inf/NaN.
MaxSrc = APFloat::getInf(SrcSema, false);
else
// Find the smallest value which is too large to represent (before
// truncation toward zero).
MaxSrc.add(APFloat(SrcSema, 1), APFloat::rmTowardPositive);
// If we're converting from __half, convert the range to float to match
// the type of src.
if (OrigSrcType->isHalfType()) {
const llvm::fltSemantics &Sema =
CGF.getContext().getFloatTypeSemantics(SrcType);
bool IsInexact;
MinSrc.convert(Sema, APFloat::rmTowardZero, &IsInexact);
MaxSrc.convert(Sema, APFloat::rmTowardZero, &IsInexact);
}
llvm::Value *GE =
Builder.CreateFCmpOGT(Src, llvm::ConstantFP::get(VMContext, MinSrc));
llvm::Value *LE =
Builder.CreateFCmpOLT(Src, llvm::ConstantFP::get(VMContext, MaxSrc));
Check = Builder.CreateAnd(GE, LE);
llvm::Constant *StaticArgs[] = {CGF.EmitCheckSourceLocation(Loc),
CGF.EmitCheckTypeDescriptor(OrigSrcType),
CGF.EmitCheckTypeDescriptor(DstType)};
CGF.EmitCheck(std::make_pair(Check, SanitizerKind::FloatCastOverflow),
SanitizerHandler::FloatCastOverflow, StaticArgs, OrigSrc);
}
// Should be called within CodeGenFunction::SanitizerScope RAII scope.
// Returns 'i1 false' when the truncation Src -> Dst was lossy.
static std::pair<ScalarExprEmitter::ImplicitConversionCheckKind,
std::pair<llvm::Value *, SanitizerMask>>
EmitIntegerTruncationCheckHelper(Value *Src, QualType SrcType, Value *Dst,
QualType DstType, CGBuilderTy &Builder) {
llvm::Type *SrcTy = Src->getType();
llvm::Type *DstTy = Dst->getType();
(void)DstTy; // Only used in assert()
// This should be truncation of integral types.
assert(Src != Dst);
assert(SrcTy->getScalarSizeInBits() > Dst->getType()->getScalarSizeInBits());
assert(isa<llvm::IntegerType>(SrcTy) && isa<llvm::IntegerType>(DstTy) &&
"non-integer llvm type");
bool SrcSigned = SrcType->isSignedIntegerOrEnumerationType();
bool DstSigned = DstType->isSignedIntegerOrEnumerationType();
// If both (src and dst) types are unsigned, then it's an unsigned truncation.
// Else, it is a signed truncation.
ScalarExprEmitter::ImplicitConversionCheckKind Kind;
SanitizerMask Mask;
if (!SrcSigned && !DstSigned) {
Kind = ScalarExprEmitter::ICCK_UnsignedIntegerTruncation;
Mask = SanitizerKind::ImplicitUnsignedIntegerTruncation;
} else {
Kind = ScalarExprEmitter::ICCK_SignedIntegerTruncation;
Mask = SanitizerKind::ImplicitSignedIntegerTruncation;
}
llvm::Value *Check = nullptr;
// 1. Extend the truncated value back to the same width as the Src.
Check = Builder.CreateIntCast(Dst, SrcTy, DstSigned, "anyext");
// 2. Equality-compare with the original source value
Check = Builder.CreateICmpEQ(Check, Src, "truncheck");
// If the comparison result is 'i1 false', then the truncation was lossy.
return std::make_pair(Kind, std::make_pair(Check, Mask));
}
static bool PromotionIsPotentiallyEligibleForImplicitIntegerConversionCheck(
QualType SrcType, QualType DstType) {
return SrcType->isIntegerType() && DstType->isIntegerType();
}
void ScalarExprEmitter::EmitIntegerTruncationCheck(Value *Src, QualType SrcType,
Value *Dst, QualType DstType,
SourceLocation Loc) {
if (!CGF.SanOpts.hasOneOf(SanitizerKind::ImplicitIntegerTruncation))
return;
// We only care about int->int conversions here.
// We ignore conversions to/from pointer and/or bool.
if (!PromotionIsPotentiallyEligibleForImplicitIntegerConversionCheck(SrcType,
DstType))
return;
unsigned SrcBits = Src->getType()->getScalarSizeInBits();
unsigned DstBits = Dst->getType()->getScalarSizeInBits();
// This must be truncation. Else we do not care.
if (SrcBits <= DstBits)
return;
assert(!DstType->isBooleanType() && "we should not get here with booleans.");
// If the integer sign change sanitizer is enabled,
// and we are truncating from larger unsigned type to smaller signed type,
// let that next sanitizer deal with it.
bool SrcSigned = SrcType->isSignedIntegerOrEnumerationType();
bool DstSigned = DstType->isSignedIntegerOrEnumerationType();
if (CGF.SanOpts.has(SanitizerKind::ImplicitIntegerSignChange) &&
(!SrcSigned && DstSigned))
return;
CodeGenFunction::SanitizerScope SanScope(&CGF);
std::pair<ScalarExprEmitter::ImplicitConversionCheckKind,
std::pair<llvm::Value *, SanitizerMask>>
Check =
EmitIntegerTruncationCheckHelper(Src, SrcType, Dst, DstType, Builder);
// If the comparison result is 'i1 false', then the truncation was lossy.
// Do we care about this type of truncation?
if (!CGF.SanOpts.has(Check.second.second))
return;
llvm::Constant *StaticArgs[] = {
CGF.EmitCheckSourceLocation(Loc), CGF.EmitCheckTypeDescriptor(SrcType),
CGF.EmitCheckTypeDescriptor(DstType),
llvm::ConstantInt::get(Builder.getInt8Ty(), Check.first)};
CGF.EmitCheck(Check.second, SanitizerHandler::ImplicitConversion, StaticArgs,
{Src, Dst});
}
// Should be called within CodeGenFunction::SanitizerScope RAII scope.
// Returns 'i1 false' when the conversion Src -> Dst changed the sign.
static std::pair<ScalarExprEmitter::ImplicitConversionCheckKind,
std::pair<llvm::Value *, SanitizerMask>>
EmitIntegerSignChangeCheckHelper(Value *Src, QualType SrcType, Value *Dst,
QualType DstType, CGBuilderTy &Builder) {
llvm::Type *SrcTy = Src->getType();
llvm::Type *DstTy = Dst->getType();
assert(isa<llvm::IntegerType>(SrcTy) && isa<llvm::IntegerType>(DstTy) &&
"non-integer llvm type");
bool SrcSigned = SrcType->isSignedIntegerOrEnumerationType();
bool DstSigned = DstType->isSignedIntegerOrEnumerationType();
(void)SrcSigned; // Only used in assert()
(void)DstSigned; // Only used in assert()
unsigned SrcBits = SrcTy->getScalarSizeInBits();
unsigned DstBits = DstTy->getScalarSizeInBits();
(void)SrcBits; // Only used in assert()
(void)DstBits; // Only used in assert()
assert(((SrcBits != DstBits) || (SrcSigned != DstSigned)) &&
"either the widths should be different, or the signednesses.");
// NOTE: zero value is considered to be non-negative.
auto EmitIsNegativeTest = [&Builder](Value *V, QualType VType,
const char *Name) -> Value * {
// Is this value a signed type?
bool VSigned = VType->isSignedIntegerOrEnumerationType();
llvm::Type *VTy = V->getType();
if (!VSigned) {
// If the value is unsigned, then it is never negative.
// FIXME: can we encounter non-scalar VTy here?
return llvm::ConstantInt::getFalse(VTy->getContext());
}
// Get the zero of the same type with which we will be comparing.
llvm::Constant *Zero = llvm::ConstantInt::get(VTy, 0);
// %V.isnegative = icmp slt %V, 0
// I.e is %V *strictly* less than zero, does it have negative value?
return Builder.CreateICmp(llvm::ICmpInst::ICMP_SLT, V, Zero,
llvm::Twine(Name) + "." + V->getName() +
".negativitycheck");
};
// 1. Was the old Value negative?
llvm::Value *SrcIsNegative = EmitIsNegativeTest(Src, SrcType, "src");
// 2. Is the new Value negative?
llvm::Value *DstIsNegative = EmitIsNegativeTest(Dst, DstType, "dst");
// 3. Now, was the 'negativity status' preserved during the conversion?
// NOTE: conversion from negative to zero is considered to change the sign.
// (We want to get 'false' when the conversion changed the sign)
// So we should just equality-compare the negativity statuses.
llvm::Value *Check = nullptr;
Check = Builder.CreateICmpEQ(SrcIsNegative, DstIsNegative, "signchangecheck");
// If the comparison result is 'false', then the conversion changed the sign.
return std::make_pair(
ScalarExprEmitter::ICCK_IntegerSignChange,
std::make_pair(Check, SanitizerKind::ImplicitIntegerSignChange));
}
void ScalarExprEmitter::EmitIntegerSignChangeCheck(Value *Src, QualType SrcType,
Value *Dst, QualType DstType,
SourceLocation Loc) {
if (!CGF.SanOpts.has(SanitizerKind::ImplicitIntegerSignChange))
return;
llvm::Type *SrcTy = Src->getType();
llvm::Type *DstTy = Dst->getType();
// We only care about int->int conversions here.
// We ignore conversions to/from pointer and/or bool.
if (!PromotionIsPotentiallyEligibleForImplicitIntegerConversionCheck(SrcType,
DstType))
return;
bool SrcSigned = SrcType->isSignedIntegerOrEnumerationType();
bool DstSigned = DstType->isSignedIntegerOrEnumerationType();
unsigned SrcBits = SrcTy->getScalarSizeInBits();
unsigned DstBits = DstTy->getScalarSizeInBits();
// Now, we do not need to emit the check in *all* of the cases.
// We can avoid emitting it in some obvious cases where it would have been
// dropped by the opt passes (instcombine) always anyways.
// If it's a cast between effectively the same type, no check.
// NOTE: this is *not* equivalent to checking the canonical types.
if (SrcSigned == DstSigned && SrcBits == DstBits)
return;
// At least one of the values needs to have signed type.
// If both are unsigned, then obviously, neither of them can be negative.
if (!SrcSigned && !DstSigned)
return;
// If the conversion is to *larger* *signed* type, then no check is needed.
// Because either sign-extension happens (so the sign will remain),
// or zero-extension will happen (the sign bit will be zero.)
if ((DstBits > SrcBits) && DstSigned)
return;
if (CGF.SanOpts.has(SanitizerKind::ImplicitSignedIntegerTruncation) &&
(SrcBits > DstBits) && SrcSigned) {
// If the signed integer truncation sanitizer is enabled,
// and this is a truncation from signed type, then no check is needed.
// Because here sign change check is interchangeable with truncation check.
return;
}
// That's it. We can't rule out any more cases with the data we have.
CodeGenFunction::SanitizerScope SanScope(&CGF);
std::pair<ScalarExprEmitter::ImplicitConversionCheckKind,
std::pair<llvm::Value *, SanitizerMask>>
Check;
// Each of these checks needs to return 'false' when an issue was detected.
ImplicitConversionCheckKind CheckKind;
llvm::SmallVector<std::pair<llvm::Value *, SanitizerMask>, 2> Checks;
// So we can 'and' all the checks together, and still get 'false',
// if at least one of the checks detected an issue.
Check = EmitIntegerSignChangeCheckHelper(Src, SrcType, Dst, DstType, Builder);
CheckKind = Check.first;
Checks.emplace_back(Check.second);
if (CGF.SanOpts.has(SanitizerKind::ImplicitSignedIntegerTruncation) &&
(SrcBits > DstBits) && !SrcSigned && DstSigned) {
// If the signed integer truncation sanitizer was enabled,
// and we are truncating from larger unsigned type to smaller signed type,
// let's handle the case we skipped in that check.
Check =
EmitIntegerTruncationCheckHelper(Src, SrcType, Dst, DstType, Builder);
CheckKind = ICCK_SignedIntegerTruncationOrSignChange;
Checks.emplace_back(Check.second);
// If the comparison result is 'i1 false', then the truncation was lossy.
}
llvm::Constant *StaticArgs[] = {
CGF.EmitCheckSourceLocation(Loc), CGF.EmitCheckTypeDescriptor(SrcType),
CGF.EmitCheckTypeDescriptor(DstType),
llvm::ConstantInt::get(Builder.getInt8Ty(), CheckKind)};
// EmitCheck() will 'and' all the checks together.
CGF.EmitCheck(Checks, SanitizerHandler::ImplicitConversion, StaticArgs,
{Src, Dst});
}
Value *ScalarExprEmitter::EmitScalarCast(Value *Src, QualType SrcType,
QualType DstType, llvm::Type *SrcTy,
llvm::Type *DstTy,
ScalarConversionOpts Opts) {
// The Element types determine the type of cast to perform.
llvm::Type *SrcElementTy;
llvm::Type *DstElementTy;
QualType SrcElementType;
QualType DstElementType;
if (SrcType->isMatrixType() && DstType->isMatrixType()) {
// Allow bitcast between matrixes of the same size.
if (SrcTy->getPrimitiveSizeInBits() == DstTy->getPrimitiveSizeInBits())
return Builder.CreateBitCast(Src, DstTy, "conv");
SrcElementTy = cast<llvm::VectorType>(SrcTy)->getElementType();
DstElementTy = cast<llvm::VectorType>(DstTy)->getElementType();
SrcElementType = SrcType->castAs<MatrixType>()->getElementType();
DstElementType = DstType->castAs<MatrixType>()->getElementType();
} else {
assert(!SrcType->isMatrixType() && !DstType->isMatrixType() &&
"cannot cast between matrix and non-matrix types");
SrcElementTy = SrcTy;
DstElementTy = DstTy;
SrcElementType = SrcType;
DstElementType = DstType;
}
if (isa<llvm::IntegerType>(SrcElementTy)) {
bool InputSigned = SrcElementType->isSignedIntegerOrEnumerationType();
if (SrcElementType->isBooleanType() && Opts.TreatBooleanAsSigned) {
InputSigned = true;
}
if (isa<llvm::IntegerType>(DstElementTy))
return Builder.CreateIntCast(Src, DstTy, InputSigned, "conv");
if (InputSigned)
return Builder.CreateSIToFP(Src, DstTy, "conv");
return Builder.CreateUIToFP(Src, DstTy, "conv");
}
if (isa<llvm::IntegerType>(DstElementTy)) {
assert(SrcElementTy->isFloatingPointTy() && "Unknown real conversion");
if (DstElementType->isSignedIntegerOrEnumerationType())
return Builder.CreateFPToSI(Src, DstTy, "conv");
return Builder.CreateFPToUI(Src, DstTy, "conv");
}
if (DstElementTy->getTypeID() < SrcElementTy->getTypeID())
return Builder.CreateFPTrunc(Src, DstTy, "conv");
return Builder.CreateFPExt(Src, DstTy, "conv");
}
/// Emit a conversion from the specified type to the specified destination type,
/// both of which are LLVM scalar types.
Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
QualType DstType,
SourceLocation Loc,
ScalarConversionOpts Opts) {
// All conversions involving fixed point types should be handled by the
// EmitFixedPoint family functions. This is done to prevent bloating up this
// function more, and although fixed point numbers are represented by
// integers, we do not want to follow any logic that assumes they should be
// treated as integers.
// TODO(leonardchan): When necessary, add another if statement checking for
// conversions to fixed point types from other types.
if (SrcType->isFixedPointType()) {
if (DstType->isBooleanType())
// It is important that we check this before checking if the dest type is
// an integer because booleans are technically integer types.
// We do not need to check the padding bit on unsigned types if unsigned
// padding is enabled because overflow into this bit is undefined
// behavior.
return Builder.CreateIsNotNull(Src, "tobool");
if (DstType->isFixedPointType() || DstType->isIntegerType() ||
DstType->isRealFloatingType())
return EmitFixedPointConversion(Src, SrcType, DstType, Loc);
llvm_unreachable(
"Unhandled scalar conversion from a fixed point type to another type.");
} else if (DstType->isFixedPointType()) {
if (SrcType->isIntegerType() || SrcType->isRealFloatingType())
// This also includes converting booleans and enums to fixed point types.
return EmitFixedPointConversion(Src, SrcType, DstType, Loc);
llvm_unreachable(
"Unhandled scalar conversion to a fixed point type from another type.");
}
QualType NoncanonicalSrcType = SrcType;
QualType NoncanonicalDstType = DstType;
SrcType = CGF.getContext().getCanonicalType(SrcType);
DstType = CGF.getContext().getCanonicalType(DstType);
if (SrcType == DstType) return Src;
if (DstType->isVoidType()) return nullptr;
llvm::Value *OrigSrc = Src;
QualType OrigSrcType = SrcType;
llvm::Type *SrcTy = Src->getType();
// Handle conversions to bool first, they are special: comparisons against 0.
if (DstType->isBooleanType())
return EmitConversionToBool(Src, SrcType);
llvm::Type *DstTy = ConvertType(DstType);
// Cast from half through float if half isn't a native type.
if (SrcType->isHalfType() && !CGF.getContext().getLangOpts().NativeHalfType) {
// Cast to FP using the intrinsic if the half type itself isn't supported.
if (DstTy->isFloatingPointTy()) {
if (CGF.getContext().getTargetInfo().useFP16ConversionIntrinsics())
return Builder.CreateCall(
CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_from_fp16, DstTy),
Src);
} else {
// Cast to other types through float, using either the intrinsic or FPExt,
// depending on whether the half type itself is supported
// (as opposed to operations on half, available with NativeHalfType).
if (CGF.getContext().getTargetInfo().useFP16ConversionIntrinsics()) {
Src = Builder.CreateCall(
CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_from_fp16,
CGF.CGM.FloatTy),
Src);
} else {
Src = Builder.CreateFPExt(Src, CGF.CGM.FloatTy, "conv");
}
SrcType = CGF.getContext().FloatTy;
SrcTy = CGF.FloatTy;
}
}
// Ignore conversions like int -> uint.
if (SrcTy == DstTy) {
if (Opts.EmitImplicitIntegerSignChangeChecks)
EmitIntegerSignChangeCheck(Src, NoncanonicalSrcType, Src,
NoncanonicalDstType, Loc);
return Src;
}
// Handle pointer conversions next: pointers can only be converted to/from
// other pointers and integers. Check for pointer types in terms of LLVM, as
// some native types (like Obj-C id) may map to a pointer type.
if (auto DstPT = dyn_cast<llvm::PointerType>(DstTy)) {
// The source value may be an integer, or a pointer.
if (isa<llvm::PointerType>(SrcTy))
return Builder.CreateBitCast(Src, DstTy, "conv");
assert(SrcType->isIntegerType() && "Not ptr->ptr or int->ptr conversion?");
// First, convert to the correct width so that we control the kind of
// extension.
llvm::Type *MiddleTy = CGF.CGM.getDataLayout().getIntPtrType(DstPT);
bool InputSigned = SrcType->isSignedIntegerOrEnumerationType();
llvm::Value* IntResult =
Builder.CreateIntCast(Src, MiddleTy, InputSigned, "conv");
// Then, cast to pointer.
return Builder.CreateIntToPtr(IntResult, DstTy, "conv");
}
if (isa<llvm::PointerType>(SrcTy)) {
// Must be an ptr to int cast.
assert(isa<llvm::IntegerType>(DstTy) && "not ptr->int?");
return Builder.CreatePtrToInt(Src, DstTy, "conv");
}
// A scalar can be splatted to an extended vector of the same element type
if (DstType->isExtVectorType() && !SrcType->isVectorType()) {
// Sema should add casts to make sure that the source expression's type is
// the same as the vector's element type (sans qualifiers)
assert(DstType->castAs<ExtVectorType>()->getElementType().getTypePtr() ==
SrcType.getTypePtr() &&
"Splatted expr doesn't match with vector element type?");
// Splat the element across to all elements
unsigned NumElements = cast<llvm::FixedVectorType>(DstTy)->getNumElements();
return Builder.CreateVectorSplat(NumElements, Src, "splat");
}
if (SrcType->isMatrixType() && DstType->isMatrixType())
return EmitScalarCast(Src, SrcType, DstType, SrcTy, DstTy, Opts);
if (isa<llvm::VectorType>(SrcTy) || isa<llvm::VectorType>(DstTy)) {
// Allow bitcast from vector to integer/fp of the same size.
unsigned SrcSize = SrcTy->getPrimitiveSizeInBits();
unsigned DstSize = DstTy->getPrimitiveSizeInBits();
if (SrcSize == DstSize)
return Builder.CreateBitCast(Src, DstTy, "conv");
// Conversions between vectors of different sizes are not allowed except
// when vectors of half are involved. Operations on storage-only half
// vectors require promoting half vector operands to float vectors and
// truncating the result, which is either an int or float vector, to a
// short or half vector.
// Source and destination are both expected to be vectors.
llvm::Type *SrcElementTy = cast<llvm::VectorType>(SrcTy)->getElementType();
llvm::Type *DstElementTy = cast<llvm::VectorType>(DstTy)->getElementType();
(void)DstElementTy;
assert(((SrcElementTy->isIntegerTy() &&
DstElementTy->isIntegerTy()) ||
(SrcElementTy->isFloatingPointTy() &&
DstElementTy->isFloatingPointTy())) &&
"unexpected conversion between a floating-point vector and an "
"integer vector");
// Truncate an i32 vector to an i16 vector.
if (SrcElementTy->isIntegerTy())
return Builder.CreateIntCast(Src, DstTy, false, "conv");
// Truncate a float vector to a half vector.
if (SrcSize > DstSize)
return Builder.CreateFPTrunc(Src, DstTy, "conv");
// Promote a half vector to a float vector.
return Builder.CreateFPExt(Src, DstTy, "conv");
}
// Finally, we have the arithmetic types: real int/float.
Value *Res = nullptr;
llvm::Type *ResTy = DstTy;
// An overflowing conversion has undefined behavior if either the source type
// or the destination type is a floating-point type. However, we consider the
// range of representable values for all floating-point types to be
// [-inf,+inf], so no overflow can ever happen when the destination type is a
// floating-point type.
if (CGF.SanOpts.has(SanitizerKind::FloatCastOverflow) &&
OrigSrcType->isFloatingType())
EmitFloatConversionCheck(OrigSrc, OrigSrcType, Src, SrcType, DstType, DstTy,
Loc);
// Cast to half through float if half isn't a native type.
if (DstType->isHalfType() && !CGF.getContext().getLangOpts().NativeHalfType) {
// Make sure we cast in a single step if from another FP type.
if (SrcTy->isFloatingPointTy()) {
// Use the intrinsic if the half type itself isn't supported
// (as opposed to operations on half, available with NativeHalfType).
if (CGF.getContext().getTargetInfo().useFP16ConversionIntrinsics())
return Builder.CreateCall(
CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_to_fp16, SrcTy), Src);
// If the half type is supported, just use an fptrunc.
return Builder.CreateFPTrunc(Src, DstTy);
}
DstTy = CGF.FloatTy;
}
Res = EmitScalarCast(Src, SrcType, DstType, SrcTy, DstTy, Opts);
if (DstTy != ResTy) {
if (CGF.getContext().getTargetInfo().useFP16ConversionIntrinsics()) {
assert(ResTy->isIntegerTy(16) && "Only half FP requires extra conversion");
Res = Builder.CreateCall(
CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_to_fp16, CGF.CGM.FloatTy),
Res);
} else {
Res = Builder.CreateFPTrunc(Res, ResTy, "conv");
}
}
if (Opts.EmitImplicitIntegerTruncationChecks)
EmitIntegerTruncationCheck(Src, NoncanonicalSrcType, Res,
NoncanonicalDstType, Loc);
if (Opts.EmitImplicitIntegerSignChangeChecks)
EmitIntegerSignChangeCheck(Src, NoncanonicalSrcType, Res,
NoncanonicalDstType, Loc);
return Res;
}
Value *ScalarExprEmitter::EmitFixedPointConversion(Value *Src, QualType SrcTy,
QualType DstTy,
SourceLocation Loc) {
llvm::FixedPointBuilder<CGBuilderTy> FPBuilder(Builder);
llvm::Value *Result;
if (SrcTy->isRealFloatingType())
Result = FPBuilder.CreateFloatingToFixed(Src,
CGF.getContext().getFixedPointSemantics(DstTy));
else if (DstTy->isRealFloatingType())
Result = FPBuilder.CreateFixedToFloating(Src,
CGF.getContext().getFixedPointSemantics(SrcTy),
ConvertType(DstTy));
else {
auto SrcFPSema = CGF.getContext().getFixedPointSemantics(SrcTy);
auto DstFPSema = CGF.getContext().getFixedPointSemantics(DstTy);
if (DstTy->isIntegerType())
Result = FPBuilder.CreateFixedToInteger(Src, SrcFPSema,
DstFPSema.getWidth(),
DstFPSema.isSigned());
else if (SrcTy->isIntegerType())
Result = FPBuilder.CreateIntegerToFixed(Src, SrcFPSema.isSigned(),
DstFPSema);
else
Result = FPBuilder.CreateFixedToFixed(Src, SrcFPSema, DstFPSema);
}
return Result;
}
/// Emit a conversion from the specified complex type to the specified
/// destination type, where the destination type is an LLVM scalar type.
Value *ScalarExprEmitter::EmitComplexToScalarConversion(
CodeGenFunction::ComplexPairTy Src, QualType SrcTy, QualType DstTy,
SourceLocation Loc) {
// Get the source element type.
SrcTy = SrcTy->castAs<ComplexType>()->getElementType();
// Handle conversions to bool first, they are special: comparisons against 0.
if (DstTy->isBooleanType()) {
// Complex != 0 -> (Real != 0) | (Imag != 0)
Src.first = EmitScalarConversion(Src.first, SrcTy, DstTy, Loc);
Src.second = EmitScalarConversion(Src.second, SrcTy, DstTy, Loc);
return Builder.CreateOr(Src.first, Src.second, "tobool");
}
// C99 6.3.1.7p2: "When a value of complex type is converted to a real type,
// the imaginary part of the complex value is discarded and the value of the
// real part is converted according to the conversion rules for the
// corresponding real type.
return EmitScalarConversion(Src.first, SrcTy, DstTy, Loc);
}
Value *ScalarExprEmitter::EmitNullValue(QualType Ty) {
return CGF.EmitFromMemory(CGF.CGM.EmitNullConstant(Ty), Ty);
}
/// Emit a sanitization check for the given "binary" operation (which
/// might actually be a unary increment which has been lowered to a binary
/// operation). The check passes if all values in \p Checks (which are \c i1),
/// are \c true.
void ScalarExprEmitter::EmitBinOpCheck(
ArrayRef<std::pair<Value *, SanitizerMask>> Checks, const BinOpInfo &Info) {
assert(CGF.IsSanitizerScope);
SanitizerHandler Check;
SmallVector<llvm::Constant *, 4> StaticData;
SmallVector<llvm::Value *, 2> DynamicData;
BinaryOperatorKind Opcode = Info.Opcode;
if (BinaryOperator::isCompoundAssignmentOp(Opcode))
Opcode = BinaryOperator::getOpForCompoundAssignment(Opcode);
StaticData.push_back(CGF.EmitCheckSourceLocation(Info.E->getExprLoc()));
const UnaryOperator *UO = dyn_cast<UnaryOperator>(Info.E);
if (UO && UO->getOpcode() == UO_Minus) {
Check = SanitizerHandler::NegateOverflow;
StaticData.push_back(CGF.EmitCheckTypeDescriptor(UO->getType()));
DynamicData.push_back(Info.RHS);
} else {
if (BinaryOperator::isShiftOp(Opcode)) {
// Shift LHS negative or too large, or RHS out of bounds.
Check = SanitizerHandler::ShiftOutOfBounds;
const BinaryOperator *BO = cast<BinaryOperator>(Info.E);
StaticData.push_back(
CGF.EmitCheckTypeDescriptor(BO->getLHS()->getType()));
StaticData.push_back(
CGF.EmitCheckTypeDescriptor(BO->getRHS()->getType()));
} else if (Opcode == BO_Div || Opcode == BO_Rem) {
// Divide or modulo by zero, or signed overflow (eg INT_MAX / -1).
Check = SanitizerHandler::DivremOverflow;
StaticData.push_back(CGF.EmitCheckTypeDescriptor(Info.Ty));
} else {
// Arithmetic overflow (+, -, *).
switch (Opcode) {
case BO_Add: Check = SanitizerHandler::AddOverflow; break;
case BO_Sub: Check = SanitizerHandler::SubOverflow; break;
case BO_Mul: Check = SanitizerHandler::MulOverflow; break;
default: llvm_unreachable("unexpected opcode for bin op check");
}
StaticData.push_back(CGF.EmitCheckTypeDescriptor(Info.Ty));
}
DynamicData.push_back(Info.LHS);
DynamicData.push_back(Info.RHS);
}
CGF.EmitCheck(Checks, Check, StaticData, DynamicData);
}
//===----------------------------------------------------------------------===//
// Visitor Methods
//===----------------------------------------------------------------------===//
Value *ScalarExprEmitter::VisitExpr(Expr *E) {
CGF.ErrorUnsupported(E, "scalar expression");
if (E->getType()->isVoidType())
return nullptr;
return llvm::UndefValue::get(CGF.ConvertType(E->getType()));
}
Value *ScalarExprEmitter::VisitShuffleVectorExpr(ShuffleVectorExpr *E) {
// Vector Mask Case
if (E->getNumSubExprs() == 2) {
Value *LHS = CGF.EmitScalarExpr(E->getExpr(0));
Value *RHS = CGF.EmitScalarExpr(E->getExpr(1));
Value *Mask;
auto *LTy = cast<llvm::FixedVectorType>(LHS->getType());
unsigned LHSElts = LTy->getNumElements();
Mask = RHS;
auto *MTy = cast<llvm::FixedVectorType>(Mask->getType());
// Mask off the high bits of each shuffle index.
Value *MaskBits =
llvm::ConstantInt::get(MTy, llvm::NextPowerOf2(LHSElts - 1) - 1);
Mask = Builder.CreateAnd(Mask, MaskBits, "mask");
// newv = undef
// mask = mask & maskbits
// for each elt
// n = extract mask i
// x = extract val n
// newv = insert newv, x, i
auto *RTy = llvm::FixedVectorType::get(LTy->getElementType(),
MTy->getNumElements());
Value* NewV = llvm::UndefValue::get(RTy);
for (unsigned i = 0, e = MTy->getNumElements(); i != e; ++i) {
Value *IIndx = llvm::ConstantInt::get(CGF.SizeTy, i);
Value *Indx = Builder.CreateExtractElement(Mask, IIndx, "shuf_idx");
Value *VExt = Builder.CreateExtractElement(LHS, Indx, "shuf_elt");
NewV = Builder.CreateInsertElement(NewV, VExt, IIndx, "shuf_ins");
}
return NewV;
}
Value* V1 = CGF.EmitScalarExpr(E->getExpr(0));
Value* V2 = CGF.EmitScalarExpr(E->getExpr(1));
SmallVector<int, 32> Indices;
for (unsigned i = 2; i < E->getNumSubExprs(); ++i) {
llvm::APSInt Idx = E->getShuffleMaskIdx(CGF.getContext(), i-2);
// Check for -1 and output it as undef in the IR.
if (Idx.isSigned() && Idx.isAllOnesValue())
Indices.push_back(-1);
else
Indices.push_back(Idx.getZExtValue());
}
return Builder.CreateShuffleVector(V1, V2, Indices, "shuffle");
}
Value *ScalarExprEmitter::VisitConvertVectorExpr(ConvertVectorExpr *E) {
QualType SrcType = E->getSrcExpr()->getType(),
DstType = E->getType();
Value *Src = CGF.EmitScalarExpr(E->getSrcExpr());
SrcType = CGF.getContext().getCanonicalType(SrcType);
DstType = CGF.getContext().getCanonicalType(DstType);
if (SrcType == DstType) return Src;
assert(SrcType->isVectorType() &&
"ConvertVector source type must be a vector");
assert(DstType->isVectorType() &&
"ConvertVector destination type must be a vector");
llvm::Type *SrcTy = Src->getType();
llvm::Type *DstTy = ConvertType(DstType);
// Ignore conversions like int -> uint.
if (SrcTy == DstTy)
return Src;
QualType SrcEltType = SrcType->castAs<VectorType>()->getElementType(),
DstEltType = DstType->castAs<VectorType>()->getElementType();
assert(SrcTy->isVectorTy() &&
"ConvertVector source IR type must be a vector");
assert(DstTy->isVectorTy() &&
"ConvertVector destination IR type must be a vector");
llvm::Type *SrcEltTy = cast<llvm::VectorType>(SrcTy)->getElementType(),
*DstEltTy = cast<llvm::VectorType>(DstTy)->getElementType();
if (DstEltType->isBooleanType()) {
assert((SrcEltTy->isFloatingPointTy() ||
isa<llvm::IntegerType>(SrcEltTy)) && "Unknown boolean conversion");
llvm::Value *Zero = llvm::Constant::getNullValue(SrcTy);
if (SrcEltTy->isFloatingPointTy()) {
return Builder.CreateFCmpUNE(Src, Zero, "tobool");
} else {
return Builder.CreateICmpNE(Src, Zero, "tobool");
}
}
// We have the arithmetic types: real int/float.
Value *Res = nullptr;
if (isa<llvm::IntegerType>(SrcEltTy)) {
bool InputSigned = SrcEltType->isSignedIntegerOrEnumerationType();
if (isa<llvm::IntegerType>(DstEltTy))
Res = Builder.CreateIntCast(Src, DstTy, InputSigned, "conv");
else if (InputSigned)
Res = Builder.CreateSIToFP(Src, DstTy, "conv");
else
Res = Builder.CreateUIToFP(Src, DstTy, "conv");
} else if (isa<llvm::IntegerType>(DstEltTy)) {
assert(SrcEltTy->isFloatingPointTy() && "Unknown real conversion");
if (DstEltType->isSignedIntegerOrEnumerationType())
Res = Builder.CreateFPToSI(Src, DstTy, "conv");
else
Res = Builder.CreateFPToUI(Src, DstTy, "conv");
} else {
assert(SrcEltTy->isFloatingPointTy() && DstEltTy->isFloatingPointTy() &&
"Unknown real conversion");
if (DstEltTy->getTypeID() < SrcEltTy->getTypeID())
Res = Builder.CreateFPTrunc(Src, DstTy, "conv");
else
Res = Builder.CreateFPExt(Src, DstTy, "conv");
}
return Res;
}
Value *ScalarExprEmitter::VisitMemberExpr(MemberExpr *E) {
if (CodeGenFunction::ConstantEmission Constant = CGF.tryEmitAsConstant(E)) {
CGF.EmitIgnoredExpr(E->getBase());
return CGF.emitScalarConstant(Constant, E);
} else {
Expr::EvalResult Result;
if (E->EvaluateAsInt(Result, CGF.getContext(), Expr::SE_AllowSideEffects)) {
llvm::APSInt Value = Result.Val.getInt();
CGF.EmitIgnoredExpr(E->getBase());
return Builder.getInt(Value);
}
}
return EmitLoadOfLValue(E);
}
Value *ScalarExprEmitter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
TestAndClearIgnoreResultAssign();
// Emit subscript expressions in rvalue context's. For most cases, this just
// loads the lvalue formed by the subscript expr. However, we have to be
// careful, because the base of a vector subscript is occasionally an rvalue,
// so we can't get it as an lvalue.
if (!E->getBase()->getType()->isVectorType())
return EmitLoadOfLValue(E);
// Handle the vector case. The base must be a vector, the index must be an
// integer value.
Value *Base = Visit(E->getBase());
Value *Idx = Visit(E->getIdx());
QualType IdxTy = E->getIdx()->getType();
if (CGF.SanOpts.has(SanitizerKind::ArrayBounds))
CGF.EmitBoundsCheck(E, E->getBase(), Idx, IdxTy, /*Accessed*/true);
return Builder.CreateExtractElement(Base, Idx, "vecext");
}
Value *ScalarExprEmitter::VisitMatrixSubscriptExpr(MatrixSubscriptExpr *E) {
TestAndClearIgnoreResultAssign();
// Handle the vector case. The base must be a vector, the index must be an
// integer value.
Value *RowIdx = Visit(E->getRowIdx());
Value *ColumnIdx = Visit(E->getColumnIdx());
Value *Matrix = Visit(E->getBase());
// TODO: Should we emit bounds checks with SanitizerKind::ArrayBounds?
llvm::MatrixBuilder<CGBuilderTy> MB(Builder);
return MB.CreateExtractElement(
Matrix, RowIdx, ColumnIdx,
E->getBase()->getType()->castAs<ConstantMatrixType>()->getNumRows());
}
static int getMaskElt(llvm::ShuffleVectorInst *SVI, unsigned Idx,
unsigned Off) {
int MV = SVI->getMaskValue(Idx);
if (MV == -1)
return -1;
return Off + MV;
}
static int getAsInt32(llvm::ConstantInt *C, llvm::Type *I32Ty) {
assert(llvm::ConstantInt::isValueValidForType(I32Ty, C->getZExtValue()) &&
"Index operand too large for shufflevector mask!");
return C->getZExtValue();
}
Value *ScalarExprEmitter::VisitInitListExpr(InitListExpr *E) {
bool Ignore = TestAndClearIgnoreResultAssign();
(void)Ignore;
assert (Ignore == false && "init list ignored");
unsigned NumInitElements = E->getNumInits();
if (E->hadArrayRangeDesignator())
CGF.ErrorUnsupported(E, "GNU array range designator extension");
llvm::VectorType *VType =
dyn_cast<llvm::VectorType>(ConvertType(E->getType()));
if (!VType) {
if (NumInitElements == 0) {
// C++11 value-initialization for the scalar.
return EmitNullValue(E->getType());
}
// We have a scalar in braces. Just use the first element.
return Visit(E->getInit(0));
}
unsigned ResElts = cast<llvm::FixedVectorType>(VType)->getNumElements();
// Loop over initializers collecting the Value for each, and remembering
// whether the source was swizzle (ExtVectorElementExpr). This will allow
// us to fold the shuffle for the swizzle into the shuffle for the vector
// initializer, since LLVM optimizers generally do not want to touch
// shuffles.
unsigned CurIdx = 0;
bool VIsUndefShuffle = false;
llvm::Value *V = llvm::UndefValue::get(VType);
for (unsigned i = 0; i != NumInitElements; ++i) {
Expr *IE = E->getInit(i);
Value *Init = Visit(IE);
SmallVector<int, 16> Args;
llvm::VectorType *VVT = dyn_cast<llvm::VectorType>(Init->getType());
// Handle scalar elements. If the scalar initializer is actually one
// element of a different vector of the same width, use shuffle instead of
// extract+insert.
if (!VVT) {
if (isa<ExtVectorElementExpr>(IE)) {
llvm::ExtractElementInst *EI = cast<llvm::ExtractElementInst>(Init);
if (cast<llvm::FixedVectorType>(EI->getVectorOperandType())
->getNumElements() == ResElts) {
llvm::ConstantInt *C = cast<llvm::ConstantInt>(EI->getIndexOperand());
Value *LHS = nullptr, *RHS = nullptr;
if (CurIdx == 0) {
// insert into undef -> shuffle (src, undef)
// shufflemask must use an i32
Args.push_back(getAsInt32(C, CGF.Int32Ty));
Args.resize(ResElts, -1);
LHS = EI->getVectorOperand();
RHS = V;
VIsUndefShuffle = true;
} else if (VIsUndefShuffle) {
// insert into undefshuffle && size match -> shuffle (v, src)
llvm::ShuffleVectorInst *SVV = cast<llvm::ShuffleVectorInst>(V);
for (unsigned j = 0; j != CurIdx; ++j)
Args.push_back(getMaskElt(SVV, j, 0));
Args.push_back(ResElts + C->getZExtValue());
Args.resize(ResElts, -1);
LHS = cast<llvm::ShuffleVectorInst>(V)->getOperand(0);
RHS = EI->getVectorOperand();
VIsUndefShuffle = false;
}
if (!Args.empty()) {
V = Builder.CreateShuffleVector(LHS, RHS, Args);
++CurIdx;
continue;
}
}
}
V = Builder.CreateInsertElement(V, Init, Builder.getInt32(CurIdx),
"vecinit");
VIsUndefShuffle = false;
++CurIdx;
continue;
}
unsigned InitElts = cast<llvm::FixedVectorType>(VVT)->getNumElements();
// If the initializer is an ExtVecEltExpr (a swizzle), and the swizzle's
// input is the same width as the vector being constructed, generate an
// optimized shuffle of the swizzle input into the result.
unsigned Offset = (CurIdx == 0) ? 0 : ResElts;
if (isa<ExtVectorElementExpr>(IE)) {
llvm::ShuffleVectorInst *SVI = cast<llvm::ShuffleVectorInst>(Init);
Value *SVOp = SVI->getOperand(0);
auto *OpTy = cast<llvm::FixedVectorType>(SVOp->getType());
if (OpTy->getNumElements() == ResElts) {
for (unsigned j = 0; j != CurIdx; ++j) {
// If the current vector initializer is a shuffle with undef, merge
// this shuffle directly into it.
if (VIsUndefShuffle) {
Args.push_back(getMaskElt(cast<llvm::ShuffleVectorInst>(V), j, 0));
} else {
Args.push_back(j);
}
}
for (unsigned j = 0, je = InitElts; j != je; ++j)
Args.push_back(getMaskElt(SVI, j, Offset));
Args.resize(ResElts, -1);
if (VIsUndefShuffle)
V = cast<llvm::ShuffleVectorInst>(V)->getOperand(0);
Init = SVOp;
}
}
// Extend init to result vector length, and then shuffle its contribution
// to the vector initializer into V.
if (Args.empty()) {
for (unsigned j = 0; j != InitElts; ++j)
Args.push_back(j);
Args.resize(ResElts, -1);
Init = Builder.CreateShuffleVector(Init, Args, "vext");
Args.clear();
for (unsigned j = 0; j != CurIdx; ++j)
Args.push_back(j);
for (unsigned j = 0; j != InitElts; ++j)
Args.push_back(j + Offset);
Args.resize(ResElts, -1);
}
// If V is undef, make sure it ends up on the RHS of the shuffle to aid
// merging subsequent shuffles into this one.
if (CurIdx == 0)
std::swap(V, Init);
V = Builder.CreateShuffleVector(V, Init, Args, "vecinit");
VIsUndefShuffle = isa<llvm::UndefValue>(Init);
CurIdx += InitElts;
}
// FIXME: evaluate codegen vs. shuffling against constant null vector.
// Emit remaining default initializers.
llvm::Type *EltTy = VType->getElementType();
// Emit remaining default initializers
for (/* Do not initialize i*/; CurIdx < ResElts; ++CurIdx) {
Value *Idx = Builder.getInt32(CurIdx);
llvm::Value *Init = llvm::Constant::getNullValue(EltTy);
V = Builder.CreateInsertElement(V, Init, Idx, "vecinit");
}
return V;
}
bool CodeGenFunction::ShouldNullCheckClassCastValue(const CastExpr *CE) {
const Expr *E = CE->getSubExpr();
if (CE->getCastKind() == CK_UncheckedDerivedToBase)
return false;
if (isa<CXXThisExpr>(E->IgnoreParens())) {
// We always assume that 'this' is never null.
return false;
}
if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(CE)) {
// And that glvalue casts are never null.
if (ICE->getValueKind() != VK_RValue)
return false;
}
return true;
}
// VisitCastExpr - Emit code for an explicit or implicit cast. Implicit casts
// have to handle a more broad range of conversions than explicit casts, as they
// handle things like function to ptr-to-function decay etc.
Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
Expr *E = CE->getSubExpr();
QualType DestTy = CE->getType();
CastKind Kind = CE->getCastKind();
// These cases are generally not written to ignore the result of
// evaluating their sub-expressions, so we clear this now.
bool Ignored = TestAndClearIgnoreResultAssign();
// Since almost all cast kinds apply to scalars, this switch doesn't have
// a default case, so the compiler will warn on a missing case. The cases
// are in the same order as in the CastKind enum.
switch (Kind) {
case CK_Dependent: llvm_unreachable("dependent cast kind in IR gen!");
case CK_BuiltinFnToFnPtr:
llvm_unreachable("builtin functions are handled elsewhere");
case CK_LValueBitCast:
case CK_ObjCObjectLValueCast: {
Address Addr = EmitLValue(E).getAddress(CGF);
Addr = Builder.CreateElementBitCast(Addr, CGF.ConvertTypeForMem(DestTy));
LValue LV = CGF.MakeAddrLValue(Addr, DestTy);
return EmitLoadOfLValue(LV, CE->getExprLoc());
}
case CK_LValueToRValueBitCast: {
LValue SourceLVal = CGF.EmitLValue(E);
Address Addr = Builder.CreateElementBitCast(SourceLVal.getAddress(CGF),
CGF.ConvertTypeForMem(DestTy));
LValue DestLV = CGF.MakeAddrLValue(Addr, DestTy);
DestLV.setTBAAInfo(TBAAAccessInfo::getMayAliasInfo());
return EmitLoadOfLValue(DestLV, CE->getExprLoc());
}
case CK_CPointerToObjCPointerCast:
case CK_BlockPointerToObjCPointerCast:
case CK_AnyPointerToBlockPointerCast:
case CK_BitCast: {
Value *Src = Visit(const_cast<Expr*>(E));
llvm::Type *SrcTy = Src->getType();
llvm::Type *DstTy = ConvertType(DestTy);
if (SrcTy->isPtrOrPtrVectorTy() && DstTy->isPtrOrPtrVectorTy() &&
SrcTy->getPointerAddressSpace() != DstTy->getPointerAddressSpace()) {
llvm_unreachable("wrong cast for pointers in different address spaces"
"(must be an address space cast)!");
}
if (CGF.SanOpts.has(SanitizerKind::CFIUnrelatedCast)) {
if (auto PT = DestTy->getAs<PointerType>())
CGF.EmitVTablePtrCheckForCast(PT->getPointeeType(), Src,
/*MayBeNull=*/true,
CodeGenFunction::CFITCK_UnrelatedCast,
CE->getBeginLoc());
}
if (CGF.CGM.getCodeGenOpts().StrictVTablePointers) {
const QualType SrcType = E->getType();
if (SrcType.mayBeNotDynamicClass() && DestTy.mayBeDynamicClass()) {
// Casting to pointer that could carry dynamic information (provided by
// invariant.group) requires launder.
Src = Builder.CreateLaunderInvariantGroup(Src);
} else if (SrcType.mayBeDynamicClass() && DestTy.mayBeNotDynamicClass()) {
// Casting to pointer that does not carry dynamic information (provided
// by invariant.group) requires stripping it. Note that we don't do it
// if the source could not be dynamic type and destination could be
// dynamic because dynamic information is already laundered. It is
// because launder(strip(src)) == launder(src), so there is no need to
// add extra strip before launder.
Src = Builder.CreateStripInvariantGroup(Src);
}
}
// Update heapallocsite metadata when there is an explicit pointer cast.
if (auto *CI = dyn_cast<llvm::CallBase>(Src)) {
if (CI->getMetadata("heapallocsite") && isa<ExplicitCastExpr>(CE)) {
QualType PointeeType = DestTy->getPointeeType();
if (!PointeeType.isNull())
CGF.getDebugInfo()->addHeapAllocSiteMetadata(CI, PointeeType,
CE->getExprLoc());
}
}
// If Src is a fixed vector and Dst is a scalable vector, and both have the
// same element type, use the llvm.experimental.vector.insert intrinsic to
// perform the bitcast.
if (const auto *FixedSrc = dyn_cast<llvm::FixedVectorType>(SrcTy)) {
if (const auto *ScalableDst = dyn_cast<llvm::ScalableVectorType>(DstTy)) {
if (FixedSrc->getElementType() == ScalableDst->getElementType()) {
llvm::Value *UndefVec = llvm::UndefValue::get(DstTy);
llvm::Value *Zero = llvm::Constant::getNullValue(CGF.CGM.Int64Ty);
return Builder.CreateInsertVector(DstTy, UndefVec, Src, Zero,
"castScalableSve");
}
}
}
// If Src is a scalable vector and Dst is a fixed vector, and both have the
// same element type, use the llvm.experimental.vector.extract intrinsic to
// perform the bitcast.
if (const auto *ScalableSrc = dyn_cast<llvm::ScalableVectorType>(SrcTy)) {
if (const auto *FixedDst = dyn_cast<llvm::FixedVectorType>(DstTy)) {
if (ScalableSrc->getElementType() == FixedDst->getElementType()) {
llvm::Value *Zero = llvm::Constant::getNullValue(CGF.CGM.Int64Ty);
return Builder.CreateExtractVector(DstTy, Src, Zero, "castFixedSve");
}
}
}
// Perform VLAT <-> VLST bitcast through memory.
// TODO: since the llvm.experimental.vector.{insert,extract} intrinsics
// require the element types of the vectors to be the same, we
// need to keep this around for casting between predicates, or more
// generally for bitcasts between VLAT <-> VLST where the element
// types of the vectors are not the same, until we figure out a better
// way of doing these casts.
if ((isa<llvm::FixedVectorType>(SrcTy) &&
isa<llvm::ScalableVectorType>(DstTy)) ||
(isa<llvm::ScalableVectorType>(SrcTy) &&
isa<llvm::FixedVectorType>(DstTy))) {
if (const CallExpr *CE = dyn_cast<CallExpr>(E)) {
// Call expressions can't have a scalar return unless the return type
// is a reference type so an lvalue can't be emitted. Create a temp
// alloca to store the call, bitcast the address then load.
QualType RetTy = CE->getCallReturnType(CGF.getContext());
Address Addr =
CGF.CreateDefaultAlignTempAlloca(SrcTy, "saved-call-rvalue");
LValue LV = CGF.MakeAddrLValue(Addr, RetTy);
CGF.EmitStoreOfScalar(Src, LV);
Addr = Builder.CreateElementBitCast(Addr, CGF.ConvertTypeForMem(DestTy),
"castFixedSve");
LValue DestLV = CGF.MakeAddrLValue(Addr, DestTy);
DestLV.setTBAAInfo(TBAAAccessInfo::getMayAliasInfo());
return EmitLoadOfLValue(DestLV, CE->getExprLoc());
}
Address Addr = EmitLValue(E).getAddress(CGF);
Addr = Builder.CreateElementBitCast(Addr, CGF.ConvertTypeForMem(DestTy));
LValue DestLV = CGF.MakeAddrLValue(Addr, DestTy);
DestLV.setTBAAInfo(TBAAAccessInfo::getMayAliasInfo());
return EmitLoadOfLValue(DestLV, CE->getExprLoc());
}
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);
}
// 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(
CGF, Visit(E), E->getType()->getPointeeType().getAddressSpace(),
DestTy->getPointeeType().getAddressSpace(), ConvertType(DestTy));
}
case CK_AtomicToNonAtomic:
case CK_NonAtomicToAtomic:
case CK_NoOp:
case CK_UserDefinedConversion:
return Visit(const_cast<Expr*>(E));
case CK_BaseToDerived: {
const CXXRecordDecl *DerivedClassDecl = DestTy->getPointeeCXXRecordDecl();
assert(DerivedClassDecl && "BaseToDerived arg isn't a C++ object pointer!");
Address Base = CGF.EmitPointerWithAlignment(E);
Address Derived =
CGF.GetAddressOfDerivedClass(Base, DerivedClassDecl,
CE->path_begin(), CE->path_end(),
CGF.ShouldNullCheckClassCastValue(CE));
// C++11 [expr.static.cast]p11: Behavior is undefined if a downcast is
// performed and the object is not of the derived type.
if (CGF.sanitizePerformTypeCheck())
CGF.EmitTypeCheck(CodeGenFunction::TCK_DowncastPointer, CE->getExprLoc(),
Derived.getPointer(), DestTy->getPointeeType());
if (CGF.SanOpts.has(SanitizerKind::CFIDerivedCast))
CGF.EmitVTablePtrCheckForCast(
DestTy->getPointeeType(), Derived.getPointer(),
/*MayBeNull=*/true, CodeGenFunction::CFITCK_DerivedCast,
CE->getBeginLoc());
return Derived.getPointer();
}
case CK_UncheckedDerivedToBase:
case CK_DerivedToBase: {
// The EmitPointerWithAlignment path does this fine; just discard
// the alignment.
return CGF.EmitPointerWithAlignment(CE).getPointer();
}
case CK_Dynamic: {
Address V = CGF.EmitPointerWithAlignment(E);
const CXXDynamicCastExpr *DCE = cast<CXXDynamicCastExpr>(CE);
return CGF.EmitDynamicCast(V, DCE);
}
case CK_ArrayToPointerDecay:
return CGF.EmitArrayToPointerDecay(E).getPointer();
case CK_FunctionToPointerDecay:
return EmitLValue(E).getPointer(CGF);
case CK_NullToPointer:
if (MustVisitNullValue(E))
CGF.EmitIgnoredExpr(E);
return CGF.CGM.getNullPointer(cast<llvm::PointerType>(ConvertType(DestTy)),
DestTy);
case CK_NullToMemberPointer: {
if (MustVisitNullValue(E))
CGF.EmitIgnoredExpr(E);
const MemberPointerType *MPT = CE->getType()->getAs<MemberPointerType>();
return CGF.CGM.getCXXABI().EmitNullMemberPointer(MPT);
}
case CK_ReinterpretMemberPointer:
case CK_BaseToDerivedMemberPointer:
case CK_DerivedToBaseMemberPointer: {
Value *Src = Visit(E);
// Note that the AST doesn't distinguish between checked and
// unchecked member pointer conversions, so we always have to
// implement checked conversions here. This is inefficient when
// actual control flow may be required in order to perform the
// check, which it is for data member pointers (but not member
// function pointers on Itanium and ARM).
return CGF.CGM.getCXXABI().EmitMemberPointerConversion(CGF, CE, Src);
}
case CK_ARCProduceObject:
return CGF.EmitARCRetainScalarExpr(E);
case CK_ARCConsumeObject:
return CGF.EmitObjCConsumeObject(E->getType(), Visit(E));
case CK_ARCReclaimReturnedObject:
return CGF.EmitARCReclaimReturnedObject(E, /*allowUnsafe*/ Ignored);
case CK_ARCExtendBlockObject:
return CGF.EmitARCExtendBlockObject(E);
case CK_CopyAndAutoreleaseBlockObject:
return CGF.EmitBlockCopyAndAutorelease(Visit(E), E->getType());
case CK_FloatingRealToComplex:
case CK_FloatingComplexCast:
case CK_IntegralRealToComplex:
case CK_IntegralComplexCast:
case CK_IntegralComplexToFloatingComplex:
case CK_FloatingComplexToIntegralComplex:
case CK_ConstructorConversion:
case CK_ToUnion:
llvm_unreachable("scalar cast to non-scalar value");
case CK_LValueToRValue:
assert(CGF.getContext().hasSameUnqualifiedType(E->getType(), DestTy));
assert(E->isGLValue() && "lvalue-to-rvalue applied to r-value!");
return Visit(const_cast<Expr*>(E));
case CK_IntegralToPointer: {
Value *Src = Visit(const_cast<Expr*>(E));
// First, convert to the correct width so that we control the kind of
// extension.
auto DestLLVMTy = ConvertType(DestTy);
llvm::Type *MiddleTy = CGF.CGM.getDataLayout().getIntPtrType(DestLLVMTy);
bool InputSigned = E->getType()->isSignedIntegerOrEnumerationType();
llvm::Value* IntResult =
Builder.CreateIntCast(Src, MiddleTy, InputSigned, "conv");
auto *IntToPtr = Builder.CreateIntToPtr(IntResult, DestLLVMTy);
if (CGF.CGM.getCodeGenOpts().StrictVTablePointers) {
// Going from integer to pointer that could be dynamic requires reloading
// dynamic information from invariant.group.
if (DestTy.mayBeDynamicClass())
IntToPtr = Builder.CreateLaunderInvariantGroup(IntToPtr);
}
return IntToPtr;
}
case CK_PointerToIntegral: {
assert(!DestTy->isBooleanType() && "bool should use PointerToBool");
auto *PtrExpr = Visit(E);
if (CGF.CGM.getCodeGenOpts().StrictVTablePointers) {
const QualType SrcType = E->getType();
// Casting to integer requires stripping dynamic information as it does
// not carries it.
if (SrcType.mayBeDynamicClass())
PtrExpr = Builder.CreateStripInvariantGroup(PtrExpr);
}
return Builder.CreatePtrToInt(PtrExpr, ConvertType(DestTy));
}
case CK_ToVoid: {
CGF.EmitIgnoredExpr(E);
return nullptr;
}
case CK_MatrixCast: {
return EmitScalarConversion(Visit(E), E->getType(), DestTy,
CE->getExprLoc());
}
case CK_VectorSplat: {
llvm::Type *DstTy = ConvertType(DestTy);
Value *Elt = Visit(const_cast<Expr*>(E));
// Splat the element across to all elements
unsigned NumElements = cast<llvm::FixedVectorType>(DstTy)->getNumElements();
return Builder.CreateVectorSplat(NumElements, Elt, "splat");
}
case CK_FixedPointCast:
return EmitScalarConversion(Visit(E), E->getType(), DestTy,
CE->getExprLoc());
case CK_FixedPointToBoolean:
assert(E->getType()->isFixedPointType() &&
"Expected src type to be fixed point type");
assert(DestTy->isBooleanType() && "Expected dest type to be boolean type");
return EmitScalarConversion(Visit(E), E->getType(), DestTy,
CE->getExprLoc());
case CK_FixedPointToIntegral:
assert(E->getType()->isFixedPointType() &&
"Expected src type to be fixed point type");
assert(DestTy->isIntegerType() && "Expected dest type to be an integer");
return EmitScalarConversion(Visit(E), E->getType(), DestTy,
CE->getExprLoc());
case CK_IntegralToFixedPoint:
assert(E->getType()->isIntegerType() &&
"Expected src type to be an integer");
assert(DestTy->isFixedPointType() &&
"Expected dest type to be fixed point type");
return EmitScalarConversion(Visit(E), E->getType(), DestTy,
CE->getExprLoc());
case CK_IntegralCast: {
ScalarConversionOpts Opts;
if (auto *ICE = dyn_cast<ImplicitCastExpr>(CE)) {
if (!ICE->isPartOfExplicitCast())
Opts = ScalarConversionOpts(CGF.SanOpts);
}
return EmitScalarConversion(Visit(E), E->getType(), DestTy,
CE->getExprLoc(), Opts);
}
case CK_IntegralToFloating:
case CK_FloatingToIntegral:
case CK_FloatingCast:
case CK_FixedPointToFloating:
case CK_FloatingToFixedPoint: {
CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, CE);
return EmitScalarConversion(Visit(E), E->getType(), DestTy,
CE->getExprLoc());
}
case CK_BooleanToSignedIntegral: {
ScalarConversionOpts Opts;
Opts.TreatBooleanAsSigned = true;
return EmitScalarConversion(Visit(E), E->getType(), DestTy,
CE->getExprLoc(), Opts);
}
case CK_IntegralToBoolean:
return EmitIntToBoolConversion(Visit(E));
case CK_PointerToBoolean:
return EmitPointerToBoolConversion(Visit(E), E->getType());
case CK_FloatingToBoolean: {
CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, CE);
return EmitFloatToBoolConversion(Visit(E));
}
case CK_MemberPointerToBoolean: {
llvm::Value *MemPtr = Visit(E);
const MemberPointerType *MPT = E->getType()->getAs<MemberPointerType>();
return CGF.CGM.getCXXABI().EmitMemberPointerIsNotNull(CGF, MemPtr, MPT);
}
case CK_FloatingComplexToReal:
case CK_IntegralComplexToReal:
return CGF.EmitComplexExpr(E, false, true).first;
case CK_FloatingComplexToBoolean:
case CK_IntegralComplexToBoolean: {