aqjune created this revision. Herald added subscribers: steakhal, martong, arphaman. Herald added a reviewer: shafik. Herald added a reviewer: NoQ. Herald added a project: All. aqjune requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
This patch adds a builtin constant that lowers to `freeze(poison)`. This is necessary to patch the intrinsics like e.g., `mm256_castsi128_si256` to be lowered to the following sequence: %a1 = freeze <2 x double> poison // <- would like to represent this as '__builtin_unspecified_value' in C/C++. %res = shufflevector <2 x double> %a0, <2 x double> %a1, <4 x i32> <i32 0, i32 1, i32 2, i32 3> Currently it is being lowered to: %res = shufflevector <2x double> %a0, undef, <4 x i32> <i32 0, i32 1, i32 -1, i32 -1> The current lowering may incorrectly introduce undefined behavior. A related, previous patch was here: https://reviews.llvm.org/D130339 Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D136737 Files: clang/include/clang-c/Index.h clang/include/clang/AST/Expr.h clang/include/clang/AST/RecursiveASTVisitor.h clang/include/clang/Basic/StmtNodes.td clang/include/clang/Serialization/ASTBitCodes.h clang/lib/AST/ASTImporter.cpp clang/lib/AST/Expr.cpp clang/lib/AST/ExprClassification.cpp clang/lib/AST/StmtPrinter.cpp clang/lib/AST/StmtProfile.cpp clang/lib/Sema/SemaExceptionSpec.cpp clang/lib/Sema/TreeTransform.h clang/lib/Serialization/ASTReaderStmt.cpp clang/lib/Serialization/ASTWriterStmt.cpp clang/lib/StaticAnalyzer/Core/ExprEngine.cpp clang/tools/libclang/CXCursor.cpp
Index: clang/tools/libclang/CXCursor.cpp =================================================================== --- clang/tools/libclang/CXCursor.cpp +++ clang/tools/libclang/CXCursor.cpp @@ -475,6 +475,10 @@ K = CXCursor_GNUNullExpr; break; + case Stmt::UnspecifiedValueExprClass: + K = CXCursor_UnspecifiedValueExpr; + break; + case Stmt::CXXStaticCastExprClass: K = CXCursor_CXXStaticCastExpr; break; Index: clang/lib/StaticAnalyzer/Core/ExprEngine.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -1889,6 +1889,7 @@ case Stmt::ObjCSelectorExprClass: case Stmt::ParenListExprClass: case Stmt::ShuffleVectorExprClass: + case Stmt::UnspecifiedValueExprClass: case Stmt::ConvertVectorExprClass: case Stmt::VAArgExprClass: case Stmt::CUDAKernelCallExprClass: Index: clang/lib/Serialization/ASTWriterStmt.cpp =================================================================== --- clang/lib/Serialization/ASTWriterStmt.cpp +++ clang/lib/Serialization/ASTWriterStmt.cpp @@ -1195,6 +1195,12 @@ Code = serialization::EXPR_GNU_NULL; } +void ASTStmtWriter::VisitUnspecifiedValueExpr(UnspecifiedValueExpr *E) { + VisitExpr(E); + Record.AddSourceLocation(E->getTokenLocation()); + Code = serialization::EXPR_UNSPECIFIED_VALUE; +} + void ASTStmtWriter::VisitShuffleVectorExpr(ShuffleVectorExpr *E) { VisitExpr(E); Record.push_back(E->getNumSubExprs()); Index: clang/lib/Serialization/ASTReaderStmt.cpp =================================================================== --- clang/lib/Serialization/ASTReaderStmt.cpp +++ clang/lib/Serialization/ASTReaderStmt.cpp @@ -1316,6 +1316,11 @@ E->setTokenLocation(readSourceLocation()); } +void ASTStmtReader::VisitUnspecifiedValueExpr(UnspecifiedValueExpr *E) { + VisitExpr(E); + E->setTokenLocation(readSourceLocation()); +} + void ASTStmtReader::VisitShuffleVectorExpr(ShuffleVectorExpr *E) { VisitExpr(E); SmallVector<Expr *, 16> Exprs; @@ -3077,6 +3082,10 @@ S = new (Context) GNUNullExpr(Empty); break; + case EXPR_UNSPECIFIED_VALUE: + S = new (Context) UnspecifiedValueExpr(Empty); + break; + case EXPR_SHUFFLE_VECTOR: S = new (Context) ShuffleVectorExpr(Empty); break; Index: clang/lib/Sema/TreeTransform.h =================================================================== --- clang/lib/Sema/TreeTransform.h +++ clang/lib/Sema/TreeTransform.h @@ -11719,6 +11719,12 @@ return E; } +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformUnspecifiedValueExpr(UnspecifiedValueExpr *E) { + return E; +} + template<typename Derived> ExprResult TreeTransform<Derived>::TransformCXXOperatorCallExpr(CXXOperatorCallExpr *E) { Index: clang/lib/Sema/SemaExceptionSpec.cpp =================================================================== --- clang/lib/Sema/SemaExceptionSpec.cpp +++ clang/lib/Sema/SemaExceptionSpec.cpp @@ -1404,6 +1404,7 @@ case Expr::SourceLocExprClass: case Expr::ConceptSpecializationExprClass: case Expr::RequiresExprClass: + case Expr::UnspecifiedValueExprClass: // These expressions can never throw. return CT_Cannot; Index: clang/lib/AST/StmtProfile.cpp =================================================================== --- clang/lib/AST/StmtProfile.cpp +++ clang/lib/AST/StmtProfile.cpp @@ -1472,6 +1472,10 @@ VisitExpr(S); } +void StmtProfiler::VisitUnspecifiedValueExpr(const UnspecifiedValueExpr *S) { + VisitExpr(S); +} + void StmtProfiler::VisitVAArgExpr(const VAArgExpr *S) { VisitExpr(S); } Index: clang/lib/AST/StmtPrinter.cpp =================================================================== --- clang/lib/AST/StmtPrinter.cpp +++ clang/lib/AST/StmtPrinter.cpp @@ -1674,6 +1674,10 @@ OS << "__null"; } +void StmtPrinter::VisitUnspecifiedValueExpr(UnspecifiedValueExpr *) { + OS << "__builtin_unspecified_value"; +} + void StmtPrinter::VisitShuffleVectorExpr(ShuffleVectorExpr *Node) { OS << "__builtin_shufflevector("; for (unsigned i = 0, e = Node->getNumSubExprs(); i != e; ++i) { Index: clang/lib/AST/ExprClassification.cpp =================================================================== --- clang/lib/AST/ExprClassification.cpp +++ clang/lib/AST/ExprClassification.cpp @@ -167,6 +167,7 @@ case Expr::OffsetOfExprClass: case Expr::CXXThrowExprClass: case Expr::ShuffleVectorExprClass: + case Expr::UnspecifiedValueExprClass: case Expr::ConvertVectorExprClass: case Expr::IntegerLiteralClass: case Expr::FixedPointLiteralClass: Index: clang/lib/AST/Expr.cpp =================================================================== --- clang/lib/AST/Expr.cpp +++ clang/lib/AST/Expr.cpp @@ -3638,6 +3638,7 @@ case SubstNonTypeTemplateParmExprClass: case MaterializeTemporaryExprClass: case ShuffleVectorExprClass: + case UnspecifiedValueExprClass: case ConvertVectorExprClass: case AsTypeExprClass: // These have a side-effect if any subexpression does. Index: clang/lib/AST/ASTImporter.cpp =================================================================== --- clang/lib/AST/ASTImporter.cpp +++ clang/lib/AST/ASTImporter.cpp @@ -618,6 +618,7 @@ ExpectedStmt VisitChooseExpr(ChooseExpr *E); ExpectedStmt VisitShuffleVectorExpr(ShuffleVectorExpr *E); ExpectedStmt VisitGNUNullExpr(GNUNullExpr *E); + ExpectedStmt VisitUnspecifiedValueExpr(UnspecifiedValueExpr *E); ExpectedStmt VisitGenericSelectionExpr(GenericSelectionExpr *E); ExpectedStmt VisitPredefinedExpr(PredefinedExpr *E); ExpectedStmt VisitDeclRefExpr(DeclRefExpr *E); @@ -6987,6 +6988,20 @@ return new (Importer.getToContext()) GNUNullExpr(*TypeOrErr, *BeginLocOrErr); } +ExpectedStmt ASTNodeImporter::VisitUnspecifiedValueExpr( + UnspecifiedValueExpr *E) { + ExpectedType TypeOrErr = import(E->getType()); + if (!TypeOrErr) + return TypeOrErr.takeError(); + + ExpectedSLoc BeginLocOrErr = import(E->getBeginLoc()); + if (!BeginLocOrErr) + return BeginLocOrErr.takeError(); + + return new (Importer.getToContext()) UnspecifiedValueExpr(*TypeOrErr, + *BeginLocOrErr); +} + ExpectedStmt ASTNodeImporter::VisitGenericSelectionExpr(GenericSelectionExpr *E) { Error Err = Error::success(); Index: clang/include/clang/Serialization/ASTBitCodes.h =================================================================== --- clang/include/clang/Serialization/ASTBitCodes.h +++ clang/include/clang/Serialization/ASTBitCodes.h @@ -1706,6 +1706,9 @@ /// A GNUNullExpr record. EXPR_GNU_NULL, + // An UnspecifiedValueExpr record. + EXPR_UNSPECIFIED_VALUE, + /// A SourceLocExpr record. EXPR_SOURCE_LOC, Index: clang/include/clang/Basic/StmtNodes.td =================================================================== --- clang/include/clang/Basic/StmtNodes.td +++ clang/include/clang/Basic/StmtNodes.td @@ -202,6 +202,7 @@ def TypoExpr : StmtNode<Expr>; def RecoveryExpr : StmtNode<Expr>; def BuiltinBitCastExpr : StmtNode<ExplicitCastExpr>; +def UnspecifiedValueExpr : StmtNode<Expr>; // Microsoft Extensions. def MSPropertyRefExpr : StmtNode<Expr>; Index: clang/include/clang/AST/RecursiveASTVisitor.h =================================================================== --- clang/include/clang/AST/RecursiveASTVisitor.h +++ clang/include/clang/AST/RecursiveASTVisitor.h @@ -2797,6 +2797,7 @@ DEF_TRAVERSE_STMT(ConvertVectorExpr, {}) DEF_TRAVERSE_STMT(StmtExpr, {}) DEF_TRAVERSE_STMT(SourceLocExpr, {}) +DEF_TRAVERSE_STMT(UnspecifiedValueExpr, {}) DEF_TRAVERSE_STMT(UnresolvedLookupExpr, { TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); Index: clang/include/clang/AST/Expr.h =================================================================== --- clang/include/clang/AST/Expr.h +++ clang/include/clang/AST/Expr.h @@ -4634,6 +4634,43 @@ } }; +/// UnspecifiedValueExpr - clang-specific value __builtin_unspecified_value. +/// This AST node represents freeze(poison) in LLVM IR. +class UnspecifiedValueExpr : public Expr { + /// TokenLoc - The location of the __builtin_specified_value keyword. + SourceLocation TokenLoc; + +public: + UnspecifiedValueExpr(QualType Ty, SourceLocation Loc) + : Expr(UnspecifiedValueExprClass, Ty, VK_PRValue, OK_Ordinary), + TokenLoc(Loc) { + setDependence(ExprDependence::None); + } + + /// Build an empty GNU __null expression. + explicit UnspecifiedValueExpr(EmptyShell Empty) : + Expr(UnspecifiedValueExprClass, Empty) { } + + /// getTokenLocation - The location of the __null token. + SourceLocation getTokenLocation() const { return TokenLoc; } + void setTokenLocation(SourceLocation L) { TokenLoc = L; } + + SourceLocation getBeginLoc() const LLVM_READONLY { return TokenLoc; } + SourceLocation getEndLoc() const LLVM_READONLY { return TokenLoc; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == UnspecifiedValueExprClass; + } + + // Iterators + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } +}; + /// Represents a call to the builtin function \c __builtin_va_arg. class VAArgExpr : public Expr { Stmt *Val; Index: clang/include/clang-c/Index.h =================================================================== --- clang/include/clang-c/Index.h +++ clang/include/clang-c/Index.h @@ -1531,7 +1531,12 @@ */ CXCursor_RequiresExpr = 154, - CXCursor_LastExpr = CXCursor_RequiresExpr, + /** + * A clang-builtin of unspecified value. + */ + CXCursor_UnspecifiedValueExpr = 155, + + CXCursor_LastExpr = CXCursor_UnspecifiedValueExpr, /* Statements */ CXCursor_FirstStmt = 200,
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits