diff options
author | Tanya Lattner <tonic@nondot.org> | 2011-06-04 00:47:47 +0000 |
---|---|---|
committer | Tanya Lattner <tonic@nondot.org> | 2011-06-04 00:47:47 +0000 |
commit | 61eee0ca33b29e102f11bab77c8b74cc00e2392b (patch) | |
tree | 6d15da9dbb7e38437454db0f20493b479bc4eedb /lib | |
parent | 9198126067a447f8aaccf9fff09be294c8bcb81e (diff) |
Add support for builtin astype:
__builtin_astype(): Used to reinterpreted as another data type of the same size using for both scalar and vector data types.
Added test case.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@132612 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/ExprClassification.cpp | 1 | ||||
-rw-r--r-- | lib/AST/ExprConstant.cpp | 1 | ||||
-rw-r--r-- | lib/AST/ItaniumMangle.cpp | 4 | ||||
-rw-r--r-- | lib/AST/StmtPrinter.cpp | 7 | ||||
-rw-r--r-- | lib/AST/StmtProfile.cpp | 4 | ||||
-rw-r--r-- | lib/CodeGen/CGExprScalar.cpp | 51 | ||||
-rw-r--r-- | lib/Parse/ParseExpr.cpp | 30 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 20 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 7 | ||||
-rw-r--r-- | lib/Serialization/ASTReaderStmt.cpp | 6 | ||||
-rw-r--r-- | lib/Serialization/ASTWriterStmt.cpp | 11 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngine.cpp | 1 |
12 files changed, 141 insertions, 2 deletions
diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp index 7e4d06ac30..d177cb5cbc 100644 --- a/lib/AST/ExprClassification.cpp +++ b/lib/AST/ExprClassification.cpp @@ -161,6 +161,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { case Expr::InitListExprClass: case Expr::SizeOfPackExprClass: case Expr::SubstNonTypeTemplateParmPackExprClass: + case Expr::AsTypeExprClass: return Cl::CL_PRValue; // Next come the complicated cases. diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 1206fe7fb3..06c5645afb 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -2770,6 +2770,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { case Expr::OpaqueValueExprClass: case Expr::PackExpansionExprClass: case Expr::SubstNonTypeTemplateParmPackExprClass: + case Expr::AsTypeExprClass: return ICEDiag(2, E->getLocStart()); case Expr::SizeOfPackExprClass: diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp index aad6e9c48d..53c204562a 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -2093,7 +2093,9 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { case Expr::VAArgExprClass: case Expr::CXXUuidofExprClass: case Expr::CXXNoexceptExprClass: - case Expr::CUDAKernelCallExprClass: { + case Expr::CUDAKernelCallExprClass: + case Expr::AsTypeExprClass: + { // As bad as this diagnostic is, it's better than crashing. Diagnostic &Diags = Context.getDiags(); unsigned DiagID = Diags.getCustomDiagID(Diagnostic::Error, diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index 1ef601c09b..87588e4518 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -1499,6 +1499,13 @@ void StmtPrinter::VisitBlockDeclRefExpr(BlockDeclRefExpr *Node) { void StmtPrinter::VisitOpaqueValueExpr(OpaqueValueExpr *Node) {} +void StmtPrinter::VisitAsTypeExpr(AsTypeExpr *Node) { + OS << "__builtin_astype("; + PrintExpr(Node->getSrcExpr()); + OS << ", " << Node->getType().getAsString(); + OS << ")"; +} + //===----------------------------------------------------------------------===// // Stmt method implementations //===----------------------------------------------------------------------===// diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp index 44818e8c08..b117cd9a52 100644 --- a/lib/AST/StmtProfile.cpp +++ b/lib/AST/StmtProfile.cpp @@ -679,6 +679,10 @@ void StmtProfiler::VisitCUDAKernelCallExpr(CUDAKernelCallExpr *S) { VisitCallExpr(S); } +void StmtProfiler::VisitAsTypeExpr(AsTypeExpr *S) { + VisitExpr(S); +} + void StmtProfiler::VisitCXXNamedCastExpr(CXXNamedCastExpr *S) { VisitExplicitCastExpr(S); } diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index b1d457589d..dff7bf45e0 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -508,6 +508,7 @@ public: Value *VisitObjCStringLiteral(const ObjCStringLiteral *E) { return CGF.EmitObjCStringLiteral(E); } + Value *VisitAsTypeExpr(AsTypeExpr *CE); }; } // end anonymous namespace. @@ -2545,6 +2546,56 @@ Value *ScalarExprEmitter::VisitBlockExpr(const BlockExpr *block) { return CGF.EmitBlockLiteral(block); } +Value *ScalarExprEmitter::VisitAsTypeExpr(AsTypeExpr *E) { + Value *Src = CGF.EmitScalarExpr(E->getSrcExpr()); + const llvm::Type * DstTy = ConvertType(E->getDstType()); + + // Going from vec4->vec3 or vec3->vec4 is a special case and requires + // a shuffle vector instead of a bitcast. + const llvm::Type *SrcTy = Src->getType(); + if (isa<llvm::VectorType>(DstTy) && isa<llvm::VectorType>(SrcTy)) { + unsigned numElementsDst = cast<llvm::VectorType>(DstTy)->getNumElements(); + unsigned numElementsSrc = cast<llvm::VectorType>(SrcTy)->getNumElements(); + if ((numElementsDst == 3 && numElementsSrc == 4) + || (numElementsDst == 4 && numElementsSrc == 3)) { + + + // In the case of going from int4->float3, a bitcast is needed before + // doing a shuffle. + const llvm::Type *srcElemTy = + cast<llvm::VectorType>(SrcTy)->getElementType(); + const llvm::Type *dstElemTy = + cast<llvm::VectorType>(DstTy)->getElementType(); + + if ((srcElemTy->isIntegerTy() && dstElemTy->isFloatTy()) + || (srcElemTy->isFloatTy() && dstElemTy->isIntegerTy())) { + // Create a float type of the same size as the source or destination. + const llvm::VectorType *newSrcTy = llvm::VectorType::get(dstElemTy, + numElementsSrc); + + Src = Builder.CreateBitCast(Src, newSrcTy, "astypeCast"); + } + + llvm::Value *UnV = llvm::UndefValue::get(Src->getType()); + + llvm::SmallVector<llvm::Constant*, 3> Args; + Args.push_back(Builder.getInt32(0)); + Args.push_back(Builder.getInt32(1)); + Args.push_back(Builder.getInt32(2)); + + if (numElementsDst == 4) + Args.push_back(llvm::UndefValue::get( + llvm::Type::getInt32Ty(CGF.getLLVMContext()))); + + llvm::Constant *Mask = llvm::ConstantVector::get(Args); + + return Builder.CreateShuffleVector(Src, UnV, Mask, "astype"); + } + } + + return Builder.CreateBitCast(Src, DstTy, "astype"); +} + //===----------------------------------------------------------------------===// // Entry Point into this File //===----------------------------------------------------------------------===// diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 25d505c2c5..89422b97fc 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -785,6 +785,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::kw___builtin_va_arg: case tok::kw___builtin_offsetof: case tok::kw___builtin_choose_expr: + case tok::kw___builtin_astype: // primary-expression: [OCL] as_type() return ParseBuiltinPrimaryExpression(); case tok::kw___null: return Actions.ActOnGNUNullExpr(ConsumeToken()); @@ -1533,6 +1534,7 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() { /// [GNU] '__builtin_choose_expr' '(' assign-expr ',' assign-expr ',' /// assign-expr ')' /// [GNU] '__builtin_types_compatible_p' '(' type-name ',' type-name ')' +/// [OCL] '__builtin_astype' '(' type-name expr ')' /// /// [GNU] offsetof-member-designator: /// [GNU] identifier @@ -1677,7 +1679,35 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() { Expr2.take(), ConsumeParen()); break; } + case tok::kw___builtin_astype: { + // The first argument is an expression to be converted, followed by a comma. + ExprResult Expr(ParseAssignmentExpression()); + if (Expr.isInvalid()) { + SkipUntil(tok::r_paren); + return ExprError(); + } + + if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "", + tok::r_paren)) + return ExprError(); + + // Second argument is the type to bitcast to. + TypeResult DestTy = ParseTypeName(); + if (DestTy.isInvalid()) + return ExprError(); + + // Attempt to consume the r-paren. + if (Tok.isNot(tok::r_paren)) { + Diag(Tok, diag::err_expected_rparen); + SkipUntil(tok::r_paren); + return ExprError(); + } + + Res = Actions.ActOnAsTypeExpr(Expr.take(), DestTy.get(), StartLoc, + ConsumeParen()); + break; } +} if (Res.isInvalid()) return ExprError(); diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 1006b15ff1..1914a6a6ba 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -4995,6 +4995,26 @@ Sema::ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc, return ActOnCallExpr(S, ConfigDR, LLLLoc, execConfig, GGGLoc, 0); } +/// ActOnAsTypeExpr - create a new asType (bitcast) from the arguments. +/// +/// __builtin_astype( value, dst type ) +/// +ExprResult Sema::ActOnAsTypeExpr(Expr *expr, ParsedType destty, + SourceLocation BuiltinLoc, + SourceLocation RParenLoc) { + ExprValueKind VK = VK_RValue; + ExprObjectKind OK = OK_Ordinary; + QualType DstTy = GetTypeFromParser(destty); + QualType SrcTy = expr->getType(); + if (Context.getTypeSize(DstTy) != Context.getTypeSize(SrcTy)) + return ExprError(Diag(BuiltinLoc, + diag::err_invalid_astype_of_different_size) + << DstTy.getAsString().c_str() + << SrcTy.getAsString().c_str() + << expr->getSourceRange()); + return Owned(new (Context) AsTypeExpr(expr, DstTy, VK, OK, BuiltinLoc, RParenLoc)); +} + /// BuildResolvedCallExpr - Build a call to a resolved expression, /// i.e. an expression not of \p OverloadTy. The expression should /// unary-convert to an expression of function-pointer or diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 9186767c03..06017e7cba 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -7877,6 +7877,13 @@ TreeTransform<Derived>::TransformBlockDeclRefExpr(BlockDeclRefExpr *E) { ND, NameInfo, 0); } +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformAsTypeExpr(AsTypeExpr *E) { + assert(false && "Cannot transform asType expressions yet"); + return SemaRef.Owned(E); +} + //===----------------------------------------------------------------------===// // Type reconstruction //===----------------------------------------------------------------------===// diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp index 918db7e367..f3f67a76c4 100644 --- a/lib/Serialization/ASTReaderStmt.cpp +++ b/lib/Serialization/ASTReaderStmt.cpp @@ -189,7 +189,7 @@ namespace clang { void VisitOpaqueValueExpr(OpaqueValueExpr *E); // CUDA Expressions - void VisitCUDAKernelCallExpr(CUDAKernelCallExpr *E); + void VisitCUDAKernelCallExpr(CUDAKernelCallExpr *E); }; } @@ -2000,6 +2000,10 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) { case EXPR_CUDA_KERNEL_CALL: S = new (Context) CUDAKernelCallExpr(*Context, Empty); break; + + case EXPR_ASTYPE: + S = new (Context) AsTypeExpr(Empty); + break; } // We hit a STMT_STOP, so we're done with this expression. diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp index a3970080fd..00e2404946 100644 --- a/lib/Serialization/ASTWriterStmt.cpp +++ b/lib/Serialization/ASTWriterStmt.cpp @@ -165,6 +165,8 @@ namespace clang { // CUDA Expressions void VisitCUDAKernelCallExpr(CUDAKernelCallExpr *E); + + void VisitAsTypeExpr(AsTypeExpr *E); }; } @@ -1433,6 +1435,15 @@ void ASTStmtWriter::VisitCUDAKernelCallExpr(CUDAKernelCallExpr *E) { } //===----------------------------------------------------------------------===// +// OpenCL Expressions and Statements. +//===----------------------------------------------------------------------===// +void ASTStmtWriter::VisitAsTypeExpr(AsTypeExpr *E) { + VisitExpr(E); + Writer.AddStmt(E->getSrcExpr()); + Code = serialization::EXPR_ASTYPE; +} + +//===----------------------------------------------------------------------===// // ASTWriter Implementation //===----------------------------------------------------------------------===// diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp index 6fd66c1f31..aed39eb0ce 100644 --- a/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -539,6 +539,7 @@ void ExprEngine::Visit(const Stmt* S, ExplodedNode* Pred, case Stmt::VAArgExprClass: case Stmt::CUDAKernelCallExprClass: case Stmt::OpaqueValueExprClass: + case Stmt::AsTypeExprClass: // Fall through. // Cases we intentionally don't evaluate, since they don't need |