Stmt *TransformVector::VisitConditionalOperator(ConditionalOperator *Node) { Expr *Cond = Node->getCond(); QualType CondTy = Cond->getType(); Expr *LHS = Node->getLHS(); Expr *RHS = Node->getRHS(); if (CondTy->isVectorType()) { // If the type of Cond is a vector type, change this expr to select(). DeclVector DeclVec; Cond = ConvertVecLiteralInExpr(DeclVec, Cond); LHS = ConvertVecLiteralInExpr(DeclVec, LHS); RHS = ConvertVecLiteralInExpr(DeclVec, RHS); if (DeclVec.size() > 0) { PushBackDeclStmts(*CurStmtVec, DeclVec); } QualType NodeTy = Node->getType(); ASTCtx.Deallocate(Node); Expr *Args[3] = { RHS, LHS, Cond }; return new (ASTCtx) CallExpr(ASTCtx, CLExprs.getExpr(CLExpressions::SELECT), Args, 3, NodeTy, VK_RValue, SourceLocation()); } else { Node->setCond(TransformExpr(Cond)); Node->setLHS(TransformExpr(LHS)); Node->setRHS(TransformExpr(RHS)); } return Node; }
static bool isTrackedVar(const VarDecl *vd, const DeclContext *dc) { if (vd->isLocalVarDecl() && !vd->hasGlobalStorage() && !vd->isExceptionVariable() && vd->getDeclContext() == dc) { QualType ty = vd->getType(); return ty->isScalarType() || ty->isVectorType(); } return false; }
void TransformVector::TransformVectorLiteralExpr( CompoundLiteralExpr *E, Expr **Args, unsigned StartPos) { InitListExpr *ILE = dyn_cast<InitListExpr>(E->getInitializer()); assert(ILE && "ERROR: Vector literal is not an InitListExpr"); QualType ETy = E->getType(); const ExtVectorType *EVT = ETy->getAs<ExtVectorType>(); unsigned NumElems = EVT->getNumElements(); unsigned VecPos = 0; bool HasOneInitElem = (ILE->getNumInits() == 1); for (unsigned i = StartPos; i < StartPos + NumElems; i++) { Expr *InitExpr = ILE->getInit(VecPos); if (!HasOneInitElem) VecPos++; if (InitExpr == NULL) { // zero Args[i] = CLExprs.getExpr(CLExpressions::ZERO); continue; } QualType InitType = InitExpr->getType(); if (!InitType->isVectorType()) { // scalar element Args[i] = TransformExpr(InitExpr); continue; } // vector element const ExtVectorType *InitVec = InitType->getAs<ExtVectorType>(); unsigned InitNumElems = InitVec->getNumElements(); // Strip off any ParenExpr or CastExprs InitExpr = InitExpr->IgnoreParenCasts(); if (CompoundLiteralExpr *CE = dyn_cast<CompoundLiteralExpr>(InitExpr)) { TransformVectorLiteralExpr(CE, Args, i); i += (InitNumElems - 1); } else { CLExpressions::ExprKind kind; for (unsigned t = 0; t < InitNumElems; ++t, ++i) { // ArraySubscriptExpr kind = (CLExpressions::ExprKind)(CLExpressions::ZERO + t); Args[i] = new (ASTCtx) ArraySubscriptExpr( InitExpr, CLExprs.getExpr(kind), InitType, VK_RValue, OK_Ordinary, SourceLocation()); } --i; } } ASTCtx.Deallocate(ILE); ASTCtx.Deallocate(E); }
// get read_image function for given Accessor FunctionDecl *ASTTranslate::getImageFunction(HipaccAccessor *Acc, MemoryAccess mem_acc) { QualType QT = Acc->getImage()->getType(); if (QT->isVectorType()) { QT = QT->getAs<VectorType>()->getElementType(); } const BuiltinType *BT = QT->getAs<BuiltinType>(); switch (BT->getKind()) { case BuiltinType::WChar_U: case BuiltinType::WChar_S: case BuiltinType::ULongLong: case BuiltinType::UInt128: case BuiltinType::LongLong: case BuiltinType::Int128: case BuiltinType::LongDouble: case BuiltinType::Void: case BuiltinType::Bool: case BuiltinType::Long: case BuiltinType::ULong: case BuiltinType::Double: default: assert(0 && "BuiltinType for OpenCL Image not supported."); case BuiltinType::Char_S: case BuiltinType::SChar: case BuiltinType::Short: case BuiltinType::Int: if (mem_acc==READ_ONLY) { return builtins.getBuiltinFunction(OPENCLBIread_imagei); } else { return builtins.getBuiltinFunction(OPENCLBIwrite_imagei); } case BuiltinType::Char_U: case BuiltinType::UChar: case BuiltinType::Char16: case BuiltinType::UShort: case BuiltinType::Char32: case BuiltinType::UInt: if (mem_acc==READ_ONLY) { return builtins.getBuiltinFunction(OPENCLBIread_imageui); } else { return builtins.getBuiltinFunction(OPENCLBIwrite_imageui); } case BuiltinType::Float: if (mem_acc==READ_ONLY) { return builtins.getBuiltinFunction(OPENCLBIread_imagef); } else { return builtins.getBuiltinFunction(OPENCLBIwrite_imagef); } } }
DefinedOrUnknownSVal SValBuilder::makeZeroVal(QualType type) { if (Loc::isLocType(type)) return makeNull(); if (type->isIntegralOrEnumerationType()) return makeIntVal(0, type); if (type->isArrayType() || type->isRecordType() || type->isVectorType() || type->isAnyComplexType()) return makeCompoundVal(type, BasicVals.getEmptySValList()); // FIXME: Handle floats. return UnknownVal(); }
void ExprEngine::VisitInitListExpr(const InitListExpr *IE, ExplodedNode *Pred, ExplodedNodeSet &Dst) { StmtNodeBuilder B(Pred, Dst, *currBldrCtx); ProgramStateRef state = Pred->getState(); const LocationContext *LCtx = Pred->getLocationContext(); QualType T = getContext().getCanonicalType(IE->getType()); unsigned NumInitElements = IE->getNumInits(); if (!IE->isGLValue() && (T->isArrayType() || T->isRecordType() || T->isVectorType() || T->isAnyComplexType())) { llvm::ImmutableList<SVal> vals = getBasicVals().getEmptySValList(); // Handle base case where the initializer has no elements. // e.g: static int* myArray[] = {}; if (NumInitElements == 0) { SVal V = svalBuilder.makeCompoundVal(T, vals); B.generateNode(IE, Pred, state->BindExpr(IE, LCtx, V)); return; } for (InitListExpr::const_reverse_iterator it = IE->rbegin(), ei = IE->rend(); it != ei; ++it) { SVal V = state->getSVal(cast<Expr>(*it), LCtx); vals = getBasicVals().prependSVal(V, vals); } B.generateNode(IE, Pred, state->BindExpr(IE, LCtx, svalBuilder.makeCompoundVal(T, vals))); return; } // Handle scalars: int{5} and int{} and GLvalues. // Note, if the InitListExpr is a GLvalue, it means that there is an address // representing it, so it must have a single init element. assert(NumInitElements <= 1); SVal V; if (NumInitElements == 0) V = getSValBuilder().makeZeroVal(T); else V = state->getSVal(IE->getInit(0), LCtx); B.generateNode(IE, Pred, state->BindExpr(IE, LCtx, V)); }
void ExprEngine::VisitInitListExpr(const InitListExpr *IE, ExplodedNode *Pred, ExplodedNodeSet &Dst) { StmtNodeBuilder B(Pred, Dst, *currBldrCtx); ProgramStateRef state = Pred->getState(); const LocationContext *LCtx = Pred->getLocationContext(); QualType T = getContext().getCanonicalType(IE->getType()); unsigned NumInitElements = IE->getNumInits(); if (T->isArrayType() || T->isRecordType() || T->isVectorType() || T->isAnyComplexType()) { llvm::ImmutableList<SVal> vals = getBasicVals().getEmptySValList(); // Handle base case where the initializer has no elements. // e.g: static int* myArray[] = {}; if (NumInitElements == 0) { SVal V = svalBuilder.makeCompoundVal(T, vals); B.generateNode(IE, Pred, state->BindExpr(IE, LCtx, V)); return; } for (InitListExpr::const_reverse_iterator it = IE->rbegin(), ei = IE->rend(); it != ei; ++it) { SVal V = state->getSVal(cast<Expr>(*it), LCtx); if (dyn_cast_or_null<CXXTempObjectRegion>(V.getAsRegion())) V = UnknownVal(); vals = getBasicVals().consVals(V, vals); } B.generateNode(IE, Pred, state->BindExpr(IE, LCtx, svalBuilder.makeCompoundVal(T, vals))); return; } // Handle scalars: int{5} and int{}. assert(NumInitElements <= 1); SVal V; if (NumInitElements == 0) V = getSValBuilder().makeZeroVal(T); else V = state->getSVal(IE->getInit(0), LCtx); B.generateNode(IE, Pred, state->BindExpr(IE, LCtx, V)); }
Stmt *TransformVector::VisitCStyleCastExpr(CStyleCastExpr *Node) { QualType NodeTy = Node->getType(); Expr *SubExpr = TransformExpr(Node->getSubExpr()); // If the type of Node is a vector type, add a vector conversion function. if (NodeTy->isVectorType()) { ASTCtx.Deallocate(Node); SourceLocation loc; Expr *args[1] = { SubExpr }; return new (ASTCtx) CallExpr(ASTCtx, CLExprs.getConvertExpr(NodeTy), args, 1, NodeTy, VK_RValue, loc); } Node->setSubExpr(SubExpr); return Node; }
// Based on QualType::isTrivial. bool isTriviallyDefaultConstructible(QualType Type, const ASTContext &Context) { if (Type.isNull()) return false; if (Type->isArrayType()) return isTriviallyDefaultConstructible(Context.getBaseElementType(Type), Context); // Return false for incomplete types after skipping any incomplete array // types which are expressly allowed by the standard and thus our API. if (Type->isIncompleteType()) return false; if (Context.getLangOpts().ObjCAutoRefCount) { switch (Type.getObjCLifetime()) { case Qualifiers::OCL_ExplicitNone: return true; case Qualifiers::OCL_Strong: case Qualifiers::OCL_Weak: case Qualifiers::OCL_Autoreleasing: return false; case Qualifiers::OCL_None: if (Type->isObjCLifetimeType()) return false; break; } } QualType CanonicalType = Type.getCanonicalType(); if (CanonicalType->isDependentType()) return false; // As an extension, Clang treats vector types as Scalar types. if (CanonicalType->isScalarType() || CanonicalType->isVectorType()) return true; if (const auto *RT = CanonicalType->getAs<RecordType>()) { return recordIsTriviallyDefaultConstructible(*RT->getDecl(), Context); } // No other types can match. return false; }
void ExprEngine::VisitInitListExpr(const InitListExpr *IE, ExplodedNode *Pred, ExplodedNodeSet &Dst) { StmtNodeBuilder B(Pred, Dst, *currentBuilderContext); const ProgramState *state = Pred->getState(); const LocationContext *LCtx = Pred->getLocationContext(); QualType T = getContext().getCanonicalType(IE->getType()); unsigned NumInitElements = IE->getNumInits(); if (T->isArrayType() || T->isRecordType() || T->isVectorType()) { llvm::ImmutableList<SVal> vals = getBasicVals().getEmptySValList(); // Handle base case where the initializer has no elements. // e.g: static int* myArray[] = {}; if (NumInitElements == 0) { SVal V = svalBuilder.makeCompoundVal(T, vals); B.generateNode(IE, Pred, state->BindExpr(IE, LCtx, V)); return; } for (InitListExpr::const_reverse_iterator it = IE->rbegin(), ei = IE->rend(); it != ei; ++it) { vals = getBasicVals().consVals(state->getSVal(cast<Expr>(*it), LCtx), vals); } B.generateNode(IE, Pred, state->BindExpr(IE, LCtx, svalBuilder.makeCompoundVal(T, vals))); return; } if (Loc::isLocType(T) || T->isIntegerType()) { assert(IE->getNumInits() == 1); const Expr *initEx = IE->getInit(0); B.generateNode(IE, Pred, state->BindExpr(IE, LCtx, state->getSVal(initEx, LCtx))); return; } llvm_unreachable("unprocessed InitListExpr type"); }
void HipaccBoundaryCondition::setConstVal(APValue &val, ASTContext &Ctx) { QualType QT = getImage()->getType(); bool isVecType = QT->isVectorType(); if (isVecType) { QT = QT->getAs<VectorType>()->getElementType(); } const BuiltinType *BT = QT->getAs<BuiltinType>(); switch (BT->getKind()) { case BuiltinType::WChar_S: case BuiltinType::WChar_U: case BuiltinType::ULongLong: case BuiltinType::UInt128: case BuiltinType::LongLong: case BuiltinType::Int128: case BuiltinType::LongDouble: case BuiltinType::Void: case BuiltinType::Bool: default: assert(0 && "BuiltinType for Boundary handling constant not supported."); case BuiltinType::Char_S: case BuiltinType::SChar: case BuiltinType::Char_U: case BuiltinType::UChar: if (isVecType) { SmallVector<Expr *, 16> initExprs; for (size_t I=0, N=val.getVectorLength(); I!=N; ++I) { APValue lane = val.getVectorElt(I); initExprs.push_back(new (Ctx) CharacterLiteral(lane.getInt().getSExtValue(), CharacterLiteral::Ascii, QT, SourceLocation())); } constExpr = new (Ctx) InitListExpr(Ctx, SourceLocation(), llvm::makeArrayRef(initExprs.data(), initExprs.size()), SourceLocation()); constExpr->setType(getImage()->getType()); } else { constExpr = new (Ctx) CharacterLiteral(val.getInt().getSExtValue(), CharacterLiteral::Ascii, QT, SourceLocation()); } break; case BuiltinType::Char16: case BuiltinType::Char32: case BuiltinType::Short: case BuiltinType::UShort: case BuiltinType::Int: case BuiltinType::UInt: case BuiltinType::Long: case BuiltinType::ULong: if (isVecType) { SmallVector<Expr *, 16> initExprs; for (size_t I=0, N=val.getVectorLength(); I!=N; ++I) { APValue lane = val.getVectorElt(I); initExprs.push_back(new (Ctx) IntegerLiteral(Ctx, lane.getInt(), QT, SourceLocation())); } constExpr = new (Ctx) InitListExpr(Ctx, SourceLocation(), llvm::makeArrayRef(initExprs.data(), initExprs.size()), SourceLocation()); constExpr->setType(getImage()->getType()); } else { constExpr = new (Ctx) IntegerLiteral(Ctx, val.getInt(), QT, SourceLocation()); } break; case BuiltinType::Float: case BuiltinType::Double: if (isVecType) { SmallVector<Expr *, 16> initExprs; for (size_t I=0, N=val.getVectorLength(); I!=N; ++I) { APValue lane = val.getVectorElt(I); initExprs.push_back(FloatingLiteral::Create(Ctx, llvm::APFloat(lane.getFloat()), false, QT, SourceLocation())); } constExpr = new (Ctx) InitListExpr(Ctx, SourceLocation(), llvm::makeArrayRef(initExprs.data(), initExprs.size()), SourceLocation()); constExpr->setType(getImage()->getType()); } else { constExpr = FloatingLiteral::Create(Ctx, llvm::APFloat(val.getFloat()), false, QT, SourceLocation()); } break; } }
Expr *TransformVector::ConvertAssignExpr(DeclVector &DeclVec, ExtVectorElementExpr *LHS, BinaryOperator::Opcode Op, Expr *BRHS) { QualType BRHSTy = BRHS->getType(); Expr *RHS = BRHS->IgnoreParenCasts(); if (!(isa<CompoundLiteralExpr>(RHS) || isa<ExtVectorElementExpr>(RHS))) { RHS = ConvertVecLiteralInExpr(DeclVec, RHS); QualType RHSTy = RHS->getType(); if (RHSTy->isVectorType() && !isa<DeclRefExpr>(RHS)) { // Make a VarDecl with RHS VarDecl *VD = NewVecLiteralVarDecl(BRHSTy); VD->setInit(RHS); DeclVec.push_back(VD); // Make a DeclRefExpr SourceLocation loc; RHS = new (ASTCtx) DeclRefExpr(VD, BRHSTy, VK_RValue, loc); } } ExprVector LHSVec; MakeElementExprs(DeclVec, LHSVec, LHS); assert((LHSVec.size() > 0) && "Wrong element exprs"); bool IsScalarRHS = RHS->getType()->isScalarType(); if (LHSVec.size() == 1 && IsScalarRHS) { return NewBinaryOperator(LHSVec[0], Op, RHS); } Expr *NewExpr = 0; if (IsScalarRHS) { // scalar RHS for (unsigned i = 0, e = LHSVec.size(); i < e; i++) { Expr *OneExpr = NewBinaryOperator(LHSVec[i], Op, RHS); if (NewExpr) { NewExpr = NewBinaryOperator(NewExpr, BO_Comma, OneExpr); } else { NewExpr = OneExpr; } } } else if (CompoundLiteralExpr *CLE = dyn_cast<CompoundLiteralExpr>(RHS)) { unsigned NumElems = LHSVec.size(); Expr **Args = new (ASTCtx) Expr*[NumElems]; TransformVectorLiteralExpr(CLE, Args, 0); for (unsigned i = 0; i < NumElems; i++) { Expr *OneExpr = NewBinaryOperator(LHSVec[i], Op, Args[i]); if (NewExpr) { NewExpr = NewBinaryOperator(NewExpr, BO_Comma, OneExpr); } else { NewExpr = OneExpr; } } } else if (ExtVectorElementExpr *EE = dyn_cast<ExtVectorElementExpr>(RHS)) { ExprVector RHSVec; MakeElementExprs(DeclVec, RHSVec, EE); assert((LHSVec.size() == RHSVec.size()) && "Different LHS and RHS?"); for (unsigned i = 0, e = LHSVec.size(); i < e; i++) { Expr *OneExpr = NewBinaryOperator(LHSVec[i], Op, RHSVec[i]); if (NewExpr) { NewExpr = NewBinaryOperator(NewExpr, BO_Comma, OneExpr); } else { NewExpr = OneExpr; } } } else { // vector RHS for (unsigned i = 0, e = LHSVec.size(); i < e; i++) { QualType Ty = LHSVec[i]->getType(); // RHS[i] ArraySubscriptExpr *ElemRHS = new (ASTCtx) ArraySubscriptExpr( RHS, CLExprs.getExpr((CLExpressions::ExprKind)(CLExpressions::ZERO + i)), Ty, VK_RValue, OK_Ordinary, SourceLocation()); Expr *OneExpr = NewBinaryOperator(LHSVec[i], Op, ElemRHS); if (NewExpr) { NewExpr = NewBinaryOperator(NewExpr, BO_Comma, OneExpr); } else { NewExpr = OneExpr; } } } return NewExpr; }
Expr *TransformVector::ConvertVecLiteralInExpr(DeclVector &DeclVec, Expr *E, bool IsTopDecl) { if (CompoundLiteralExpr *CLE = dyn_cast<CompoundLiteralExpr>(E)) { QualType LitTy = CLE->getType(); if (LitTy->isVectorType()) { // vector literal VecLiteralMode = true; Expr *Init = ConvertVecLiteralInExpr(DeclVec, CLE->getInitializer()); CLE->setInitializer(Init); VecLiteralMode = false; // Make a VarDecl with an initialization expr. VarDecl *VD = NewVecLiteralVarDecl(LitTy); VD->setInit(CLE); DeclVec.push_back(VD); // Return a DeclRefExpr that refers above VarDecl. return new (ASTCtx) DeclRefExpr(VD, LitTy, VK_RValue, SourceLocation()); } else { Expr *Init = ConvertVecLiteralInExpr(DeclVec, CLE->getInitializer()); CLE->setInitializer(Init); } return CLE; } else if (ExtVectorElementExpr *EVEE = dyn_cast<ExtVectorElementExpr>(E)) { unsigned NumElems = EVEE->getNumElements(); Expr *NewE = TransformExpr(E); if (IsTopDecl && NumElems > 1) { // vector literal VarDecl *VD = NewVecLiteralVarDecl(EVEE->getType()); VD->setInit(NewE); DeclVec.push_back(VD); // Return a DeclRefExpr that refers above VarDecl. SourceLocation loc; return new (ASTCtx) DeclRefExpr(VD, VD->getType(), VK_RValue, loc); } return NewE; } else if (CompoundAssignOperator *CA = dyn_cast<CompoundAssignOperator>(E)) { Expr *CLHS = CA->getLHS(); Expr *CRHS = CA->getRHS(); if (ExtVectorElementExpr *LHS = dyn_cast<ExtVectorElementExpr>(CLHS)) { Expr *NewE = ConvertAssignExpr(DeclVec, LHS, CA->getOpcode(), CRHS); ASTCtx.Deallocate(CA); return NewE; } else { // LHS & RHS CA->setLHS(ConvertVecLiteralInExpr(DeclVec, CLHS)); CA->setRHS(ConvertVecLiteralInExpr(DeclVec, CRHS)); return CA; } } else if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(E)) { Expr *BLHS = BinOp->getLHS(); Expr *BRHS = BinOp->getRHS(); BinaryOperatorKind Op = BinOp->getOpcode(); if (Op == BO_Assign) { if (ExtVectorElementExpr *LHS = dyn_cast<ExtVectorElementExpr>(BLHS)) { Expr *NewE = ConvertAssignExpr(DeclVec, LHS, Op, BRHS); ASTCtx.Deallocate(BinOp); return NewE; } } // LHS & RHS BinOp->setLHS(ConvertVecLiteralInExpr(DeclVec, BLHS)); BinOp->setRHS(ConvertVecLiteralInExpr(DeclVec, BRHS)); return BinOp; } else if (ParenExpr *PE = dyn_cast<ParenExpr>(E)) { PE->setSubExpr(ConvertVecLiteralInExpr(DeclVec, PE->getSubExpr())); return PE; } else if (UnaryOperator *UOp = dyn_cast<UnaryOperator>(E)) { UOp->setSubExpr(ConvertVecLiteralInExpr(DeclVec, UOp->getSubExpr())); return UOp; } else if (ArraySubscriptExpr *ASE = dyn_cast<ArraySubscriptExpr>(E)) { ASE->setLHS(ConvertVecLiteralInExpr(DeclVec, ASE->getLHS())); ASE->setRHS(ConvertVecLiteralInExpr(DeclVec, ASE->getRHS())); return ASE; } else if (CallExpr *Call = dyn_cast<CallExpr>(E)) { for (unsigned i = 0, e = Call->getNumArgs(); i != e; ++i) { Call->setArg(i, ConvertVecLiteralInExpr(DeclVec, Call->getArg(i))); } // If a vload function exists in a vector literal, it can be // code-motioned in order to improve performance. if (VecLiteralMode) { Expr *Callee = Call->getCallee(); if (CLUtils::IsVectorDataFunction(Callee) != -1) { QualType CallTy = Call->getType(); VarDecl *VD = NewVecLiteralVarDecl(CallTy); VD->setInit(Call); DeclVec.push_back(VD); SourceLocation loc; return new (ASTCtx) DeclRefExpr(VD, CallTy, VK_RValue, loc); } } return Call; } else if (CStyleCastExpr *CSCE = dyn_cast<CStyleCastExpr>(E)) { CSCE->setSubExpr(ConvertVecLiteralInExpr(DeclVec, CSCE->getSubExpr())); return CSCE; } else if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) { ICE->setSubExpr(ConvertVecLiteralInExpr(DeclVec, ICE->getSubExpr())); return ICE; } else if (ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E)) { return TransformExpr(CO); } else if (InitListExpr *ILE = dyn_cast<InitListExpr>(E)) { for (unsigned i = 0, e = ILE->getNumInits(); i != e; ++i) { if (Expr *init = ILE->getInit(i)) { init = ConvertVecLiteralInExpr(DeclVec, init); ILE->setInit(i, init); } } return ILE; } else if (DesignatedInitExpr *DIE = dyn_cast<DesignatedInitExpr>(E)) { DIE->setInit(ConvertVecLiteralInExpr(DeclVec, DIE->getInit())); return DIE; } return E; }
/// CheckStaticCast - Check that a static_cast\<DestType\>(SrcExpr) is valid. /// Refer to C++ 5.2.9 for details. Static casts are mostly used for making /// implicit conversions explicit and getting rid of data loss warnings. void CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType, const SourceRange &OpRange) { // The order the tests is not entirely arbitrary. There is one conversion // that can be handled in two different ways. Given: // struct A {}; // struct B : public A { // B(); B(const A&); // }; // const A &a = B(); // the cast static_cast<const B&>(a) could be seen as either a static // reference downcast, or an explicit invocation of the user-defined // conversion using B's conversion constructor. // DR 427 specifies that the downcast is to be applied here. // FIXME: With N2812, casts to rvalue refs will change. // C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void". if (DestType->isVoidType()) { return; } // C++ 5.2.9p5, reference downcast. // See the function for details. // DR 427 specifies that this is to be applied before paragraph 2. if (TryStaticReferenceDowncast(Self, SrcExpr, DestType, OpRange) > TSC_NotApplicable) { return; } // N2844 5.2.9p3: An lvalue of type "cv1 T1" can be cast to type "rvalue // reference to cv2 T2" if "cv2 T2" is reference-compatible with "cv1 T1". if (TryLValueToRValueCast(Self, SrcExpr, DestType, OpRange) > TSC_NotApplicable) { return; } // C++ 5.2.9p2: An expression e can be explicitly converted to a type T // [...] if the declaration "T t(e);" is well-formed, [...]. if (TryStaticImplicitCast(Self, SrcExpr, DestType, OpRange) > TSC_NotApplicable) { return; } // C++ 5.2.9p6: May apply the reverse of any standard conversion, except // lvalue-to-rvalue, array-to-pointer, function-to-pointer, and boolean // conversions, subject to further restrictions. // Also, C++ 5.2.9p1 forbids casting away constness, which makes reversal // of qualification conversions impossible. // The lvalue-to-rvalue, array-to-pointer and function-to-pointer conversions // are applied to the expression. QualType OrigSrcType = SrcExpr->getType(); Self.DefaultFunctionArrayConversion(SrcExpr); QualType SrcType = Self.Context.getCanonicalType(SrcExpr->getType()); // Reverse integral promotion/conversion. All such conversions are themselves // again integral promotions or conversions and are thus already handled by // p2 (TryDirectInitialization above). // (Note: any data loss warnings should be suppressed.) // The exception is the reverse of enum->integer, i.e. integer->enum (and // enum->enum). See also C++ 5.2.9p7. // The same goes for reverse floating point promotion/conversion and // floating-integral conversions. Again, only floating->enum is relevant. if (DestType->isEnumeralType()) { if (SrcType->isComplexType() || SrcType->isVectorType()) { // Fall through - these cannot be converted. } else if (SrcType->isArithmeticType() || SrcType->isEnumeralType()) { return; } } // Reverse pointer upcast. C++ 4.10p3 specifies pointer upcast. // C++ 5.2.9p8 additionally disallows a cast path through virtual inheritance. if (TryStaticPointerDowncast(Self, SrcType, DestType, OpRange) > TSC_NotApplicable) { return; } // Reverse member pointer conversion. C++ 4.11 specifies member pointer // conversion. C++ 5.2.9p9 has additional information. // DR54's access restrictions apply here also. if (TryStaticMemberPointerUpcast(Self, SrcType, DestType, OpRange) > TSC_NotApplicable) { return; } // Reverse pointer conversion to void*. C++ 4.10.p2 specifies conversion to // void*. C++ 5.2.9p10 specifies additional restrictions, which really is // just the usual constness stuff. if (const PointerType *SrcPointer = SrcType->getAsPointerType()) { QualType SrcPointee = SrcPointer->getPointeeType(); if (SrcPointee->isVoidType()) { if (const PointerType *DestPointer = DestType->getAsPointerType()) { QualType DestPointee = DestPointer->getPointeeType(); if (DestPointee->isIncompleteOrObjectType()) { // This is definitely the intended conversion, but it might fail due // to a const violation. if (!DestPointee.isAtLeastAsQualifiedAs(SrcPointee)) { Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_const_away) << "static_cast" << DestType << OrigSrcType << OpRange; } return; } } } } // We tried everything. Everything! Nothing works! :-( // FIXME: Error reporting could be a lot better. Should store the reason why // every substep failed and, at the end, select the most specific and report // that. Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_generic) << "static_cast" << DestType << OrigSrcType << OpRange; }
// access image memory at given index Expr *ASTTranslate::accessMemImgAt(DeclRefExpr *LHS, HipaccAccessor *Acc, MemoryAccess mem_acc, Expr *idx_x, Expr *idx_y) { Expr *result, *coord; // mark image as being used within the kernel Kernel->setUsed(LHS->getNameInfo().getAsString()); // construct coordinate: (int2)(gid_x, gid_y) coord = createBinaryOperator(Ctx, idx_x, idx_y, BO_Comma, Ctx.IntTy); coord = createParenExpr(Ctx, coord); QualType QTcoord = simdTypes.getSIMDType(Ctx.IntTy, "int", SIMD2); coord = createCStyleCastExpr(Ctx, QTcoord, CK_VectorSplat, coord, nullptr, Ctx.getTrivialTypeSourceInfo(QTcoord)); FunctionDecl *image_function = getImageFunction(Acc, mem_acc); // create function call for image objects in OpenCL if (mem_acc == READ_ONLY) { // parameters for read_image SmallVector<Expr *, 16> args; args.push_back(LHS); args.push_back(kernelSamplerRef); args.push_back(coord); result = createFunctionCall(Ctx, image_function, args); QualType QT = Acc->getImage()->getType(); if (QT->isVectorType()) { SmallVector<Expr *, 16> args; args.push_back(result); result = createFunctionCall(Ctx, getConvertFunction(QT), args); } else { result = createExtVectorElementExpr(Ctx, QT, result, "x"); } } else { QualType QT; // determine cast type for write_image functions if (image_function == builtins.getBuiltinFunction(OPENCLBIwrite_imagei)) { QT = simdTypes.getSIMDType(Ctx.IntTy, "int", SIMD4); } else if (image_function == builtins.getBuiltinFunction(OPENCLBIwrite_imageui)) { QT = simdTypes.getSIMDType(Ctx.UnsignedIntTy, "uint", SIMD4); } else { QT = simdTypes.getSIMDType(Ctx.FloatTy, "float", SIMD4); } // writeImageRHS is set by VisitBinaryOperator - side effect if (!writeImageRHS->getType()->isVectorType()) { // introduce temporary for propagating the RHS to a vector std::string tmp_lit("_tmp" + std::to_string(literalCount++)); VarDecl *tmp_decl = createVarDecl(Ctx, kernelDecl, tmp_lit, QT, writeImageRHS); DeclContext *DC = FunctionDecl::castToDeclContext(kernelDecl); DC->addDecl(tmp_decl); DeclRefExpr *tmp_dre = createDeclRefExpr(Ctx, tmp_decl); preStmts.push_back(createDeclStmt(Ctx, tmp_decl)); preCStmt.push_back(curCStmt); writeImageRHS = tmp_dre; } if (writeImageRHS->getType() != QT) { // convert to proper vector type SmallVector<Expr *, 16> args; args.push_back(writeImageRHS); writeImageRHS = createFunctionCall(Ctx, getConvertFunction(QT), args); } // parameters for write_image SmallVector<Expr *, 16> args; args.push_back(LHS); args.push_back(coord); args.push_back(writeImageRHS); result = createFunctionCall(Ctx, image_function, args); } return result; }
// get tex1Dfetch function for given Accessor FunctionDecl *ASTTranslate::getTextureFunction(HipaccAccessor *Acc, MemoryAccess mem_acc) { QualType QT = Acc->getImage()->getType(); bool isVecType = QT->isVectorType(); if (isVecType) { QT = QT->getAs<VectorType>()->getElementType(); } const BuiltinType *BT = QT->getAs<BuiltinType>(); bool isOneDim = false, isLdg = false; switch (Kernel->useTextureMemory(Acc)) { default: break; case Texture::Linear1D: isOneDim = true; break; case Texture::Ldg: isLdg = true; break; } switch (BT->getKind()) { case BuiltinType::WChar_U: case BuiltinType::WChar_S: case BuiltinType::ULongLong: case BuiltinType::UInt128: case BuiltinType::LongLong: case BuiltinType::Int128: case BuiltinType::LongDouble: case BuiltinType::Void: case BuiltinType::Bool: case BuiltinType::Long: case BuiltinType::ULong: case BuiltinType::Double: default: assert(0 && "BuiltinType for CUDA texture not supported."); #define GET_BUILTIN_FUNCTION(TYPE) \ (mem_acc == READ_ONLY ? \ (isLdg ? \ (isVecType ? builtins.getBuiltinFunction(CUDABI__ldg ## E4 ## TYPE) : \ builtins.getBuiltinFunction(CUDABI__ldg ## TYPE)) : \ (isOneDim ? \ (isVecType ? builtins.getBuiltinFunction(CUDABItex1Dfetch ## E4 ## TYPE) : \ builtins.getBuiltinFunction(CUDABItex1Dfetch ## TYPE)) : \ (isVecType ? builtins.getBuiltinFunction(CUDABItex2D ## E4 ## TYPE) : \ builtins.getBuiltinFunction(CUDABItex2D ## TYPE)))) : \ (isVecType ? builtins.getBuiltinFunction(CUDABIsurf2Dwrite ## E4 ## TYPE) : \ builtins.getBuiltinFunction(CUDABIsurf2Dwrite ## TYPE))) case BuiltinType::Char_S: case BuiltinType::SChar: return GET_BUILTIN_FUNCTION(Sc); case BuiltinType::Char_U: case BuiltinType::UChar: return GET_BUILTIN_FUNCTION(Uc); case BuiltinType::Short: return GET_BUILTIN_FUNCTION(s); case BuiltinType::Char16: case BuiltinType::UShort: return GET_BUILTIN_FUNCTION(Us); case BuiltinType::Int: return GET_BUILTIN_FUNCTION(i); case BuiltinType::Char32: case BuiltinType::UInt: return GET_BUILTIN_FUNCTION(Ui); case BuiltinType::Float: return GET_BUILTIN_FUNCTION(f); #undef GET_BUILTIN_FUNCTION } }