diff options
Diffstat (limited to 'clang')
77 files changed, 1741 insertions, 455 deletions
diff --git a/clang/include/clang/AST/Attr.h b/clang/include/clang/AST/Attr.h index fe388b9..ce273c1 100644 --- a/clang/include/clang/AST/Attr.h +++ b/clang/include/clang/AST/Attr.h @@ -239,6 +239,8 @@ class HLSLSemanticAttr : public HLSLAnnotationAttr { LLVM_PREFERRED_TYPE(bool) unsigned SemanticExplicitIndex : 1; + Decl *TargetDecl = nullptr; + protected: HLSLSemanticAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo, attr::Kind AK, bool IsLateParsed, @@ -259,6 +261,11 @@ public: unsigned getSemanticIndex() const { return SemanticIndex; } + bool isSemanticIndexExplicit() const { return SemanticExplicitIndex; } + + void setTargetDecl(Decl *D) { TargetDecl = D; } + Decl *getTargetDecl() const { return TargetDecl; } + // Implement isa/cast/dyncast/etc. static bool classof(const Attr *A) { return A->getKind() >= attr::FirstHLSLSemanticAttr && diff --git a/clang/include/clang/AST/StmtOpenACC.h b/clang/include/clang/AST/StmtOpenACC.h index 4d52805..ae80297 100644 --- a/clang/include/clang/AST/StmtOpenACC.h +++ b/clang/include/clang/AST/StmtOpenACC.h @@ -821,6 +821,9 @@ public: struct StmtInfo { const Expr *V; const Expr *X; + // Listed as 'expr' in the standard, this is typically a generic expression + // as a component. + const Expr *RefExpr; // TODO: OpenACC: We should expand this as we're implementing the other // atomic construct kinds. }; diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index b320f4b..749f531 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -787,6 +787,8 @@ class HLSLSemanticAttr<bit Indexable> : HLSLAnnotationAttr { let Spellings = []; let Subjects = SubjectList<[ParmVar, Field, Function]>; let LangOpts = [HLSL]; + let Args = [DeclArgument<Named, "Target">, IntArgument<"SemanticIndex">, + BoolArgument<"SemanticExplicitIndex">]; } /// A target-specific attribute. This class is meant to be used as a mixin diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index a350acd..a2c2021 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -4727,6 +4727,13 @@ def PtrauthStringDiscriminator : Builtin { let Prototype = "size_t(char const*)"; } +// AllocToken builtins. +def InferAllocToken : Builtin { + let Spellings = ["__builtin_infer_alloc_token"]; + let Attributes = [NoThrow, Const, Pure, CustomTypeChecking, Constexpr, UnevaluatedArguments]; + let Prototype = "size_t(...)"; +} + // OpenCL v2.0 s6.13.16, s9.17.3.5 - Pipe functions. // We need the generic prototype, since the packet type could be anything. def ReadPipe : OCLPipeLangBuiltin { diff --git a/clang/include/clang/Basic/BuiltinsX86.td b/clang/include/clang/Basic/BuiltinsX86.td index 54b3ce0..8332eac 100644 --- a/clang/include/clang/Basic/BuiltinsX86.td +++ b/clang/include/clang/Basic/BuiltinsX86.td @@ -123,13 +123,13 @@ let Attributes = [Const, NoThrow, RequiredVectorWidth<128>] in { } } - let Features = "ssse3" in { - def psignb128 : X86Builtin<"_Vector<16, char>(_Vector<16, char>, _Vector<16, char>)">; - def psignw128 : X86Builtin<"_Vector<8, short>(_Vector<8, short>, _Vector<8, short>)">; - def psignd128 : X86Builtin<"_Vector<4, int>(_Vector<4, int>, _Vector<4, int>)">; - } - let Features = "ssse3", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<128>] in { + def psignb128 + : X86Builtin<"_Vector<16, char>(_Vector<16, char>, _Vector<16, char>)">; + def psignw128 + : X86Builtin<"_Vector<8, short>(_Vector<8, short>, _Vector<8, short>)">; + def psignd128 + : X86Builtin<"_Vector<4, int>(_Vector<4, int>, _Vector<4, int>)">; def pmulhrsw128 : X86Builtin<"_Vector<8, short>(_Vector<8, short>, _Vector<8, short>)">; def pmaddubsw128 : X86Builtin<"_Vector<8, short>(_Vector<16, char>, _Vector<16, char>)">; def pshufb128 : X86Builtin<"_Vector<16, char>(_Vector<16, char>, _Vector<16, char>)">; @@ -603,10 +603,9 @@ let Features = "avx2", Attributes = [NoThrow, Const, RequiredVectorWidth<256>] i def mpsadbw256 : X86Builtin<"_Vector<32, char>(_Vector<32, char>, _Vector<32, char>, _Constant char)">; def palignr256 : X86Builtin<"_Vector<32, char>(_Vector<32, char>, " "_Vector<32, char>, _Constant int)">; - def psadbw256 : X86Builtin<"_Vector<4, long long int>(_Vector<32, char>, _Vector<32, char>)">; - def psignb256 : X86Builtin<"_Vector<32, char>(_Vector<32, char>, _Vector<32, char>)">; - def psignw256 : X86Builtin<"_Vector<16, short>(_Vector<16, short>, _Vector<16, short>)">; - def psignd256 : X86Builtin<"_Vector<8, int>(_Vector<8, int>, _Vector<8, int>)">; + def psadbw256 + : X86Builtin< + "_Vector<4, long long int>(_Vector<32, char>, _Vector<32, char>)">; def psllw256 : X86Builtin<"_Vector<16, short>(_Vector<16, short>, _Vector<8, short>)">; def pslldqi256_byteshift : X86Builtin<"_Vector<32, char>(_Vector<32, char>, _Constant int)">; def pslld256 : X86Builtin<"_Vector<8, int>(_Vector<8, int>, _Vector<4, int>)">; @@ -677,7 +676,15 @@ let Features = "avx2", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWi def phsubw256 : X86Builtin<"_Vector<16, short>(_Vector<16, short>, _Vector<16, short>)">; def phsubd256 : X86Builtin<"_Vector<8, int>(_Vector<8, int>, _Vector<8, int>)">; def phsubsw256 : X86Builtin<"_Vector<16, short>(_Vector<16, short>, _Vector<16, short>)">; - + + def psignb256 + : X86Builtin<"_Vector<32, char>(_Vector<32, char>, _Vector<32, char>)">; + def psignw256 + : X86Builtin< + "_Vector<16, short>(_Vector<16, short>, _Vector<16, short>)">; + def psignd256 + : X86Builtin<"_Vector<8, int>(_Vector<8, int>, _Vector<8, int>)">; + def pshuflw256 : X86Builtin<"_Vector<16, short>(_Vector<16, short>, _Constant int)">; def pshufhw256 : X86Builtin<"_Vector<16, short>(_Vector<16, short>, _Constant int)">; def pshufd256 : X86Builtin<"_Vector<8, int>(_Vector<8, int>, _Constant int)">; diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td b/clang/include/clang/Basic/DiagnosticASTKinds.td index 0be9146f..5c462f9 100644 --- a/clang/include/clang/Basic/DiagnosticASTKinds.td +++ b/clang/include/clang/Basic/DiagnosticASTKinds.td @@ -403,6 +403,12 @@ def note_constexpr_assumption_failed : Note< def note_constexpr_countzeroes_zero : Note< "evaluation of %select{__builtin_elementwise_clzg|__builtin_elementwise_ctzg}0 " "with a zero value is undefined">; +def note_constexpr_infer_alloc_token_type_inference_failed : Note< + "could not infer allocation type for __builtin_infer_alloc_token">; +def note_constexpr_infer_alloc_token_no_metadata : Note< + "could not get token metadata for inferred type">; +def note_constexpr_infer_alloc_token_stateful_mode : Note< + "stateful alloc token mode not supported in constexpr">; def err_experimental_clang_interp_failed : Error< "the experimental clang interpreter failed to evaluate an expression">; diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td index 64391de..9e34416 100644 --- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td @@ -404,10 +404,6 @@ def warn_hlsl_langstd_minimal : "recommend using %1 instead">, InGroup<HLSLDXCCompat>; -def err_hlsl_semantic_missing : Error<"semantic annotations must be present " - "for all input and outputs of an entry " - "function or patch constant function">; - // ClangIR frontend errors def err_cir_to_cir_transform_failed : Error< "CIR-to-CIR transformation failed">, DefaultFatal; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 20b4994..13f0d59 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -13173,6 +13173,7 @@ def err_hlsl_duplicate_parameter_modifier : Error<"duplicate parameter modifier def err_hlsl_missing_semantic_annotation : Error< "semantic annotations must be present for all parameters of an entry " "function or patch constant function">; +def note_hlsl_semantic_used_here : Note<"%0 used here">; def err_hlsl_unknown_semantic : Error<"unknown HLSL semantic %0">; def err_hlsl_semantic_output_not_supported : Error<"semantic %0 does not support output">; diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 86d09d7..2b361ed 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -4053,6 +4053,43 @@ def CIR_ExpectOp : CIR_Op<"expect", [ } //===----------------------------------------------------------------------===// +// PrefetchOp +//===----------------------------------------------------------------------===// + +def CIR_PrefetchOp : CIR_Op<"prefetch"> { + let summary = "Prefetch operation"; + let description = [{ + The `cir.prefetch` operation is a hint to the code generator to insert a + prefetch instruction if supported; otherwise, it is a noop. Prefetches + have no effect on the behavior of the program but can change its + performance characteristics. + + ```mlir + cir.prefetch(%0 : !cir.ptr<!void>) locality(1) write + ``` + + $locality is a temporal locality specifier ranging from (0) - no locality, + to (3) - extremely local, keep in cache. If $locality is not present, the + default value is 3. + + $isWrite specifies whether the prefetch is for a 'read' or 'write'. If + $isWrite is not specified, it means that prefetch is prepared for 'read'. + }]; + + let arguments = (ins CIR_VoidPtrType:$addr, + DefaultValuedAttr<ConfinedAttr<I32Attr, [IntMinValue<0>, IntMaxValue<3>]>, + "3">:$locality, + UnitAttr:$isWrite); + + let assemblyFormat = [{ + (`write` $isWrite^) : (`read`)? + `locality` `(` $locality `)` + $addr `:` qualified(type($addr)) + attr-dict + }]; +} + +//===----------------------------------------------------------------------===// // PtrDiffOp //===----------------------------------------------------------------------===// diff --git a/clang/include/clang/Driver/CommonArgs.h b/clang/include/clang/Driver/CommonArgs.h index 23426c0..ac17d62 100644 --- a/clang/include/clang/Driver/CommonArgs.h +++ b/clang/include/clang/Driver/CommonArgs.h @@ -76,6 +76,9 @@ void SplitDebugInfo(const ToolChain &TC, Compilation &C, const Tool &T, const JobAction &JA, const llvm::opt::ArgList &Args, const InputInfo &Output, const char *OutFile); +void addDTLTOOptions(const ToolChain &ToolChain, const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs); + void addLTOOptions(const ToolChain &ToolChain, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs, const InputInfo &Output, const InputInfoList &Inputs, bool IsThinLTO); diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h index f9d3a4ea..8c3b6ae 100644 --- a/clang/include/clang/Sema/SemaHLSL.h +++ b/clang/include/clang/Sema/SemaHLSL.h @@ -130,9 +130,6 @@ public: bool ActOnUninitializedVarDecl(VarDecl *D); void ActOnEndOfTranslationUnit(TranslationUnitDecl *TU); void CheckEntryPoint(FunctionDecl *FD); - bool isSemanticValid(FunctionDecl *FD, DeclaratorDecl *D); - void CheckSemanticAnnotation(FunctionDecl *EntryPoint, const Decl *Param, - const HLSLAnnotationAttr *AnnotationAttr); bool CheckResourceBinOp(BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr, SourceLocation Loc); void DiagnoseAttrStageMismatch( @@ -179,17 +176,17 @@ public: bool handleResourceTypeAttr(QualType T, const ParsedAttr &AL); template <typename T> - T *createSemanticAttr(const ParsedAttr &AL, + T *createSemanticAttr(const AttributeCommonInfo &ACI, NamedDecl *TargetDecl, std::optional<unsigned> Location) { - T *Attr = ::new (getASTContext()) T(getASTContext(), AL); - if (Attr->isSemanticIndexable()) - Attr->setSemanticIndex(Location ? *Location : 0); - else if (Location.has_value()) { + T *Attr = + ::new (getASTContext()) T(getASTContext(), ACI, TargetDecl, + Location.value_or(0), Location.has_value()); + + if (!Attr->isSemanticIndexable() && Location.has_value()) { Diag(Attr->getLocation(), diag::err_hlsl_semantic_indexing_not_supported) << Attr->getAttrName()->getName(); return nullptr; } - return Attr; } @@ -247,10 +244,25 @@ private: IdentifierInfo *RootSigOverrideIdent = nullptr; + struct SemanticInfo { + HLSLSemanticAttr *Semantic; + std::optional<uint32_t> Index; + }; + private: void collectResourceBindingsOnVarDecl(VarDecl *D); void collectResourceBindingsOnUserRecordDecl(const VarDecl *VD, const RecordType *RT); + + void checkSemanticAnnotation(FunctionDecl *EntryPoint, const Decl *Param, + const HLSLSemanticAttr *SemanticAttr); + HLSLSemanticAttr *createSemantic(const SemanticInfo &Semantic, + DeclaratorDecl *TargetDecl); + bool determineActiveSemanticOnScalar(FunctionDecl *FD, DeclaratorDecl *D, + SemanticInfo &ActiveSemantic); + bool determineActiveSemantic(FunctionDecl *FD, DeclaratorDecl *D, + SemanticInfo &ActiveSemantic); + void processExplicitBindingsOnDecl(VarDecl *D); void diagnoseAvailabilityViolations(TranslationUnitDecl *TU); diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp index f15b3c1..836d22f 100644 --- a/clang/lib/AST/ByteCode/Compiler.cpp +++ b/clang/lib/AST/ByteCode/Compiler.cpp @@ -1842,7 +1842,6 @@ bool Compiler<Emitter>::visitInitList(ArrayRef<const Expr *> Inits, const Expr *Init, PrimType T, bool Activate = false) -> bool { InitStackScope<Emitter> ISS(this, isa<CXXDefaultInitExpr>(Init)); - InitLinkScope<Emitter> ILS(this, InitLink::Field(FieldToInit->Offset)); if (!this->visit(Init)) return false; @@ -5385,55 +5384,57 @@ bool Compiler<Emitter>::VisitCXXThisExpr(const CXXThisExpr *E) { // instance pointer of the current function frame, but e.g. to the declaration // currently being initialized. Here we emit the necessary instruction(s) for // this scenario. - if (!InitStackActive) + if (!InitStackActive || InitStack.empty()) return this->emitThis(E); - if (!InitStack.empty()) { - // If our init stack is, for example: - // 0 Stack: 3 (decl) - // 1 Stack: 6 (init list) - // 2 Stack: 1 (field) - // 3 Stack: 6 (init list) - // 4 Stack: 1 (field) - // - // We want to find the LAST element in it that's an init list, - // which is marked with the K_InitList marker. The index right - // before that points to an init list. We need to find the - // elements before the K_InitList element that point to a base - // (e.g. a decl or This), optionally followed by field, elem, etc. - // In the example above, we want to emit elements [0..2]. - unsigned StartIndex = 0; - unsigned EndIndex = 0; - // Find the init list. - for (StartIndex = InitStack.size() - 1; StartIndex > 0; --StartIndex) { - if (InitStack[StartIndex].Kind == InitLink::K_InitList || - InitStack[StartIndex].Kind == InitLink::K_This) { - EndIndex = StartIndex; - --StartIndex; - break; - } + // If our init stack is, for example: + // 0 Stack: 3 (decl) + // 1 Stack: 6 (init list) + // 2 Stack: 1 (field) + // 3 Stack: 6 (init list) + // 4 Stack: 1 (field) + // + // We want to find the LAST element in it that's an init list, + // which is marked with the K_InitList marker. The index right + // before that points to an init list. We need to find the + // elements before the K_InitList element that point to a base + // (e.g. a decl or This), optionally followed by field, elem, etc. + // In the example above, we want to emit elements [0..2]. + unsigned StartIndex = 0; + unsigned EndIndex = 0; + // Find the init list. + for (StartIndex = InitStack.size() - 1; StartIndex > 0; --StartIndex) { + if (InitStack[StartIndex].Kind == InitLink::K_InitList || + InitStack[StartIndex].Kind == InitLink::K_This) { + EndIndex = StartIndex; + --StartIndex; + break; } + } - // Walk backwards to find the base. - for (; StartIndex > 0; --StartIndex) { - if (InitStack[StartIndex].Kind == InitLink::K_InitList) - continue; + // Walk backwards to find the base. + for (; StartIndex > 0; --StartIndex) { + if (InitStack[StartIndex].Kind == InitLink::K_InitList) + continue; - if (InitStack[StartIndex].Kind != InitLink::K_Field && - InitStack[StartIndex].Kind != InitLink::K_Elem) - break; - } + if (InitStack[StartIndex].Kind != InitLink::K_Field && + InitStack[StartIndex].Kind != InitLink::K_Elem) + break; + } - // Emit the instructions. - for (unsigned I = StartIndex; I != EndIndex; ++I) { - if (InitStack[I].Kind == InitLink::K_InitList) - continue; - if (!InitStack[I].template emit<Emitter>(this, E)) - return false; - } - return true; + if (StartIndex == 0 && EndIndex == 0) + EndIndex = InitStack.size() - 1; + + assert(StartIndex < EndIndex); + + // Emit the instructions. + for (unsigned I = StartIndex; I != (EndIndex + 1); ++I) { + if (InitStack[I].Kind == InitLink::K_InitList) + continue; + if (!InitStack[I].template emit<Emitter>(this, E)) + return false; } - return this->emitThis(E); + return true; } template <class Emitter> bool Compiler<Emitter>::visitStmt(const Stmt *S) { @@ -6295,6 +6296,10 @@ bool Compiler<Emitter>::compileConstructor(const CXXConstructorDecl *Ctor) { } assert(NestedField); + unsigned FirstLinkOffset = + R->getField(cast<FieldDecl>(IFD->chain()[0]))->Offset; + InitStackScope<Emitter> ISS(this, isa<CXXDefaultInitExpr>(InitExpr)); + InitLinkScope<Emitter> ILS(this, InitLink::Field(FirstLinkOffset)); if (!emitFieldInitializer(NestedField, NestedFieldOffset, InitExpr, IsUnion)) return false; diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp index 2d5ad4a..ff50e6d 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp @@ -12,12 +12,14 @@ #include "InterpHelpers.h" #include "PrimType.h" #include "Program.h" +#include "clang/AST/InferAlloc.h" #include "clang/AST/OSLog.h" #include "clang/AST/RecordLayout.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/TargetBuiltins.h" #include "clang/Basic/TargetInfo.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/Support/AllocToken.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/SipHash.h" @@ -1307,6 +1309,45 @@ interp__builtin_ptrauth_string_discriminator(InterpState &S, CodePtr OpPC, return true; } +static bool interp__builtin_infer_alloc_token(InterpState &S, CodePtr OpPC, + const InterpFrame *Frame, + const CallExpr *Call) { + const ASTContext &ASTCtx = S.getASTContext(); + uint64_t BitWidth = ASTCtx.getTypeSize(ASTCtx.getSizeType()); + auto Mode = + ASTCtx.getLangOpts().AllocTokenMode.value_or(llvm::DefaultAllocTokenMode); + uint64_t MaxTokens = + ASTCtx.getLangOpts().AllocTokenMax.value_or(~0ULL >> (64 - BitWidth)); + + // We do not read any of the arguments; discard them. + for (int I = Call->getNumArgs() - 1; I >= 0; --I) + discard(S.Stk, *S.getContext().classify(Call->getArg(I))); + + // Note: Type inference from a surrounding cast is not supported in + // constexpr evaluation. + QualType AllocType = infer_alloc::inferPossibleType(Call, ASTCtx, nullptr); + if (AllocType.isNull()) { + S.CCEDiag(Call, + diag::note_constexpr_infer_alloc_token_type_inference_failed); + return false; + } + + auto ATMD = infer_alloc::getAllocTokenMetadata(AllocType, ASTCtx); + if (!ATMD) { + S.CCEDiag(Call, diag::note_constexpr_infer_alloc_token_no_metadata); + return false; + } + + auto MaybeToken = llvm::getAllocToken(Mode, *ATMD, MaxTokens); + if (!MaybeToken) { + S.CCEDiag(Call, diag::note_constexpr_infer_alloc_token_stateful_mode); + return false; + } + + pushInteger(S, llvm::APInt(BitWidth, *MaybeToken), ASTCtx.getSizeType()); + return true; +} + static bool interp__builtin_operator_new(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call) { @@ -3694,6 +3735,9 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call, case Builtin::BI__builtin_ptrauth_string_discriminator: return interp__builtin_ptrauth_string_discriminator(S, OpPC, Frame, Call); + case Builtin::BI__builtin_infer_alloc_token: + return interp__builtin_infer_alloc_token(S, OpPC, Frame, Call); + case Builtin::BI__noop: pushInteger(S, 0, Call->getType()); return true; @@ -3809,6 +3853,21 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call, return interp__builtin_ia32_movmsk_op(S, OpPC, Call); } + case X86::BI__builtin_ia32_psignb128: + case X86::BI__builtin_ia32_psignb256: + case X86::BI__builtin_ia32_psignw128: + case X86::BI__builtin_ia32_psignw256: + case X86::BI__builtin_ia32_psignd128: + case X86::BI__builtin_ia32_psignd256: + return interp__builtin_elementwise_int_binop( + S, OpPC, Call, [](const APInt &AElem, const APInt &BElem) { + if (BElem.isZero()) + return APInt::getZero(AElem.getBitWidth()); + if (BElem.isNegative()) + return -AElem; + return AElem; + }); + case clang::X86::BI__builtin_ia32_pavgb128: case clang::X86::BI__builtin_ia32_pavgw128: case clang::X86::BI__builtin_ia32_pavgb256: diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 00aaaab..2bd4476 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -44,6 +44,7 @@ #include "clang/AST/CharUnits.h" #include "clang/AST/CurrentSourceLocExprScope.h" #include "clang/AST/Expr.h" +#include "clang/AST/InferAlloc.h" #include "clang/AST/OSLog.h" #include "clang/AST/OptionalDiagnostic.h" #include "clang/AST/RecordLayout.h" @@ -12312,6 +12313,20 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) { return Success(APValue(ResultElements.data(), ResultElements.size()), E); } + case X86::BI__builtin_ia32_psignb128: + case X86::BI__builtin_ia32_psignb256: + case X86::BI__builtin_ia32_psignw128: + case X86::BI__builtin_ia32_psignw256: + case X86::BI__builtin_ia32_psignd128: + case X86::BI__builtin_ia32_psignd256: + return EvaluateBinOpExpr([](const APInt &AElem, const APInt &BElem) { + if (BElem.isZero()) + return APInt::getZero(AElem.getBitWidth()); + if (BElem.isNegative()) + return -AElem; + return AElem; + }); + case X86::BI__builtin_ia32_blendvpd: case X86::BI__builtin_ia32_blendvpd256: case X86::BI__builtin_ia32_blendvps: @@ -14649,6 +14664,27 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, return Success(Result, E); } + case Builtin::BI__builtin_infer_alloc_token: { + // If we fail to infer a type, this fails to be a constant expression; this + // can be checked with __builtin_constant_p(...). + QualType AllocType = infer_alloc::inferPossibleType(E, Info.Ctx, nullptr); + if (AllocType.isNull()) + return Error( + E, diag::note_constexpr_infer_alloc_token_type_inference_failed); + auto ATMD = infer_alloc::getAllocTokenMetadata(AllocType, Info.Ctx); + if (!ATMD) + return Error(E, diag::note_constexpr_infer_alloc_token_no_metadata); + auto Mode = + Info.getLangOpts().AllocTokenMode.value_or(llvm::DefaultAllocTokenMode); + uint64_t BitWidth = Info.Ctx.getTypeSize(Info.Ctx.getSizeType()); + uint64_t MaxTokens = + Info.getLangOpts().AllocTokenMax.value_or(~0ULL >> (64 - BitWidth)); + auto MaybeToken = llvm::getAllocToken(Mode, *ATMD, MaxTokens); + if (!MaybeToken) + return Error(E, diag::note_constexpr_infer_alloc_token_stateful_mode); + return Success(llvm::APInt(BitWidth, *MaybeToken), E); + } + case Builtin::BI__builtin_ffs: case Builtin::BI__builtin_ffsl: case Builtin::BI__builtin_ffsll: { diff --git a/clang/lib/AST/StmtOpenACC.cpp b/clang/lib/AST/StmtOpenACC.cpp index 2b56c1e..462a10d 100644 --- a/clang/lib/AST/StmtOpenACC.cpp +++ b/clang/lib/AST/StmtOpenACC.cpp @@ -324,6 +324,18 @@ OpenACCAtomicConstruct *OpenACCAtomicConstruct::Create( return Inst; } +static std::pair<const Expr *, const Expr *> getBinaryOpArgs(const Expr *Op) { + if (const auto *BO = dyn_cast<BinaryOperator>(Op)) { + assert(BO->getOpcode() == BO_Assign); + return {BO->getLHS(), BO->getRHS()}; + } + + const auto *OO = cast<CXXOperatorCallExpr>(Op); + assert(OO->getOperator() == OO_Equal); + + return {OO->getArg(0), OO->getArg(1)}; +} + const OpenACCAtomicConstruct::StmtInfo OpenACCAtomicConstruct::getAssociatedStmtInfo() const { // This ends up being a vastly simplified version of SemaOpenACCAtomic, since @@ -333,27 +345,35 @@ OpenACCAtomicConstruct::getAssociatedStmtInfo() const { switch (AtomicKind) { case OpenACCAtomicKind::None: - case OpenACCAtomicKind::Write: case OpenACCAtomicKind::Update: case OpenACCAtomicKind::Capture: - assert(false && "Only 'read' has been implemented here"); + assert(false && "Only 'read'/'write' have been implemented here"); return {}; case OpenACCAtomicKind::Read: { // Read only supports the format 'v = x'; where both sides are a scalar // expression. This can come in 2 forms; BinaryOperator or // CXXOperatorCallExpr (rarely). - const Expr *AssignExpr = cast<const Expr>(getAssociatedStmt()); - if (const auto *BO = dyn_cast<BinaryOperator>(AssignExpr)) { - assert(BO->getOpcode() == BO_Assign); - return {BO->getLHS()->IgnoreImpCasts(), BO->getRHS()->IgnoreImpCasts()}; - } - - const auto *OO = cast<CXXOperatorCallExpr>(AssignExpr); - assert(OO->getOperator() == OO_Equal); - - return {OO->getArg(0)->IgnoreImpCasts(), OO->getArg(1)->IgnoreImpCasts()}; + std::pair<const Expr *, const Expr *> BinaryArgs = + getBinaryOpArgs(cast<const Expr>(getAssociatedStmt())); + // We want the L-value for each side, so we ignore implicit casts. + return {BinaryArgs.first->IgnoreImpCasts(), + BinaryArgs.second->IgnoreImpCasts(), /*expr=*/nullptr}; } + case OpenACCAtomicKind::Write: { + // Write supports only the format 'x = expr', where the expression is scalar + // type, and 'x' is a scalar l value. As above, this can come in 2 forms; + // Binary Operator or CXXOperatorCallExpr. + std::pair<const Expr *, const Expr *> BinaryArgs = + getBinaryOpArgs(cast<const Expr>(getAssociatedStmt())); + // We want the L-value for ONLY the X side, so we ignore implicit casts. For + // the right side (the expr), we emit it as an r-value so we need to + // maintain implicit casts. + return {/*v=*/nullptr, BinaryArgs.first->IgnoreImpCasts(), + BinaryArgs.second}; } + } + + llvm_unreachable("unknown OpenACC atomic kind"); } OpenACCCacheConstruct *OpenACCCacheConstruct::CreateEmpty(const ASTContext &C, diff --git a/clang/lib/Analysis/FlowSensitive/Models/UncheckedStatusOrAccessModel.cpp b/clang/lib/Analysis/FlowSensitive/Models/UncheckedStatusOrAccessModel.cpp index 598d33a..90551c2 100644 --- a/clang/lib/Analysis/FlowSensitive/Models/UncheckedStatusOrAccessModel.cpp +++ b/clang/lib/Analysis/FlowSensitive/Models/UncheckedStatusOrAccessModel.cpp @@ -168,6 +168,15 @@ static auto isNotOkStatusCall() { "::absl::UnimplementedError", "::absl::UnknownError")))); } +static auto isPointerComparisonOperatorCall(std::string operator_name) { + using namespace ::clang::ast_matchers; // NOLINT: Too many names + return binaryOperator(hasOperatorName(operator_name), + hasLHS(hasType(hasCanonicalType(pointerType( + pointee(anyOf(statusOrType(), statusType())))))), + hasRHS(hasType(hasCanonicalType(pointerType( + pointee(anyOf(statusOrType(), statusType()))))))); +} + static auto buildDiagnoseMatchSwitch(const UncheckedStatusOrAccessModelOptions &Options) { return CFGMatchSwitchBuilder<const Environment, @@ -438,6 +447,58 @@ static void transferComparisonOperator(const CXXOperatorCallExpr *Expr, State.Env.setValue(*Expr, *LhsAndRhsVal); } +static RecordStorageLocation *getPointeeLocation(const Expr &Expr, + Environment &Env) { + if (auto *PointerVal = Env.get<PointerValue>(Expr)) + return dyn_cast<RecordStorageLocation>(&PointerVal->getPointeeLoc()); + return nullptr; +} + +static BoolValue *evaluatePointerEquality(const Expr *LhsExpr, + const Expr *RhsExpr, + Environment &Env) { + assert(LhsExpr->getType()->isPointerType()); + assert(RhsExpr->getType()->isPointerType()); + RecordStorageLocation *LhsStatusLoc = nullptr; + RecordStorageLocation *RhsStatusLoc = nullptr; + if (isStatusOrType(LhsExpr->getType()->getPointeeType()) && + isStatusOrType(RhsExpr->getType()->getPointeeType())) { + auto *LhsStatusOrLoc = getPointeeLocation(*LhsExpr, Env); + auto *RhsStatusOrLoc = getPointeeLocation(*RhsExpr, Env); + if (LhsStatusOrLoc == nullptr || RhsStatusOrLoc == nullptr) + return nullptr; + LhsStatusLoc = &locForStatus(*LhsStatusOrLoc); + RhsStatusLoc = &locForStatus(*RhsStatusOrLoc); + } else if (isStatusType(LhsExpr->getType()->getPointeeType()) && + isStatusType(RhsExpr->getType()->getPointeeType())) { + LhsStatusLoc = getPointeeLocation(*LhsExpr, Env); + RhsStatusLoc = getPointeeLocation(*RhsExpr, Env); + } + if (LhsStatusLoc == nullptr || RhsStatusLoc == nullptr) + return nullptr; + auto &LhsOkVal = valForOk(*LhsStatusLoc, Env); + auto &RhsOkVal = valForOk(*RhsStatusLoc, Env); + auto &Res = Env.makeAtomicBoolValue(); + auto &A = Env.arena(); + Env.assume(A.makeImplies( + Res.formula(), A.makeEquals(LhsOkVal.formula(), RhsOkVal.formula()))); + return &Res; +} + +static void transferPointerComparisonOperator(const BinaryOperator *Expr, + LatticeTransferState &State, + bool IsNegative) { + auto *LhsAndRhsVal = + evaluatePointerEquality(Expr->getLHS(), Expr->getRHS(), State.Env); + if (LhsAndRhsVal == nullptr) + return; + + if (IsNegative) + State.Env.setValue(*Expr, State.Env.makeNot(*LhsAndRhsVal)); + else + State.Env.setValue(*Expr, *LhsAndRhsVal); +} + static void transferOkStatusCall(const CallExpr *Expr, const MatchFinder::MatchResult &, LatticeTransferState &State) { @@ -455,6 +516,18 @@ static void transferNotOkStatusCall(const CallExpr *Expr, State.Env.assume(A.makeNot(OkVal.formula())); } +static void transferEmplaceCall(const CXXMemberCallExpr *Expr, + const MatchFinder::MatchResult &, + LatticeTransferState &State) { + RecordStorageLocation *StatusOrLoc = + getImplicitObjectLocation(*Expr, State.Env); + if (StatusOrLoc == nullptr) + return; + + auto &OkVal = valForOk(locForStatus(*StatusOrLoc), State.Env); + State.Env.assume(OkVal.formula()); +} + CFGMatchSwitch<LatticeTransferState> buildTransferMatchSwitch(ASTContext &Ctx, CFGMatchSwitchBuilder<LatticeTransferState> Builder) { @@ -482,8 +555,24 @@ buildTransferMatchSwitch(ASTContext &Ctx, transferComparisonOperator(Expr, State, /*IsNegative=*/true); }) + .CaseOfCFGStmt<BinaryOperator>( + isPointerComparisonOperatorCall("=="), + [](const BinaryOperator *Expr, const MatchFinder::MatchResult &, + LatticeTransferState &State) { + transferPointerComparisonOperator(Expr, State, + /*IsNegative=*/false); + }) + .CaseOfCFGStmt<BinaryOperator>( + isPointerComparisonOperatorCall("!="), + [](const BinaryOperator *Expr, const MatchFinder::MatchResult &, + LatticeTransferState &State) { + transferPointerComparisonOperator(Expr, State, + /*IsNegative=*/true); + }) .CaseOfCFGStmt<CallExpr>(isOkStatusCall(), transferOkStatusCall) .CaseOfCFGStmt<CallExpr>(isNotOkStatusCall(), transferNotOkStatusCall) + .CaseOfCFGStmt<CXXMemberCallExpr>(isStatusOrMemberCallWithName("emplace"), + transferEmplaceCall) .Build(); } diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp index 27c4d11..62fa04e 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp @@ -454,6 +454,27 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID, assert(!cir::MissingFeatures::coroSizeBuiltinCall()); return getUndefRValue(e->getType()); } + case Builtin::BI__builtin_prefetch: { + auto evaluateOperandAsInt = [&](const Expr *arg) { + Expr::EvalResult res; + [[maybe_unused]] bool evalSucceed = + arg->EvaluateAsInt(res, cgm.getASTContext()); + assert(evalSucceed && "expression should be able to evaluate as int"); + return res.Val.getInt().getZExtValue(); + }; + + bool isWrite = false; + if (e->getNumArgs() > 1) + isWrite = evaluateOperandAsInt(e->getArg(1)); + + int locality = 3; + if (e->getNumArgs() > 2) + locality = evaluateOperandAsInt(e->getArg(2)); + + mlir::Value address = emitScalarExpr(e->getArg(0)); + cir::PrefetchOp::create(builder, loc, address, locality, isWrite); + return RValue::get(nullptr); + } } // If this is an alias for a lib function (e.g. __builtin_sin), emit diff --git a/clang/lib/CIR/CodeGen/CIRGenCXXABI.h b/clang/lib/CIR/CodeGen/CIRGenCXXABI.h index c78f9b0..d3c7dac0 100644 --- a/clang/lib/CIR/CodeGen/CIRGenCXXABI.h +++ b/clang/lib/CIR/CodeGen/CIRGenCXXABI.h @@ -124,6 +124,8 @@ public: virtual void emitRethrow(CIRGenFunction &cgf, bool isNoReturn) = 0; virtual void emitThrow(CIRGenFunction &cgf, const CXXThrowExpr *e) = 0; + virtual void emitBadCastCall(CIRGenFunction &cgf, mlir::Location loc) = 0; + virtual mlir::Attribute getAddrOfRTTIDescriptor(mlir::Location loc, QualType ty) = 0; diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp index 9df88ad..df6ee56 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp @@ -2065,7 +2065,11 @@ mlir::Value CIRGenFunction::emitAlloca(StringRef name, mlir::Type ty, // a surrounding cir.scope, make sure the alloca ends up in the surrounding // scope instead. This is necessary in order to guarantee all SSA values are // reachable during cleanups. - assert(!cir::MissingFeatures::tryOp()); + if (auto tryOp = + llvm::dyn_cast_if_present<cir::TryOp>(entryBlock->getParentOp())) { + if (auto scopeOp = llvm::dyn_cast<cir::ScopeOp>(tryOp->getParentOp())) + entryBlock = &scopeOp.getScopeRegion().front(); + } return emitAlloca(name, ty, loc, alignment, builder.getBestAllocaInsertPoint(entryBlock), arraySize); diff --git a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp index fe9e210..a3cdf19 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp @@ -801,6 +801,26 @@ void CIRGenFunction::emitDeleteCall(const FunctionDecl *deleteFD, emitNewDeleteCall(*this, deleteFD, deleteFTy, deleteArgs); } +static mlir::Value emitDynamicCastToNull(CIRGenFunction &cgf, + mlir::Location loc, QualType destTy) { + mlir::Type destCIRTy = cgf.convertType(destTy); + assert(mlir::isa<cir::PointerType>(destCIRTy) && + "result of dynamic_cast should be a ptr"); + + if (!destTy->isPointerType()) { + mlir::Region *currentRegion = cgf.getBuilder().getBlock()->getParent(); + /// C++ [expr.dynamic.cast]p9: + /// A failed cast to reference type throws std::bad_cast + cgf.cgm.getCXXABI().emitBadCastCall(cgf, loc); + + // The call to bad_cast will terminate the current block. Create a new block + // to hold any follow up code. + cgf.getBuilder().createBlock(currentRegion, currentRegion->end()); + } + + return cgf.getBuilder().getNullPtr(destCIRTy, loc); +} + mlir::Value CIRGenFunction::emitDynamicCast(Address thisAddr, const CXXDynamicCastExpr *dce) { mlir::Location loc = getLoc(dce->getSourceRange()); @@ -831,10 +851,8 @@ mlir::Value CIRGenFunction::emitDynamicCast(Address thisAddr, assert(srcRecordTy->isRecordType() && "source type must be a record type!"); assert(!cir::MissingFeatures::emitTypeCheck()); - if (dce->isAlwaysNull()) { - cgm.errorNYI(dce->getSourceRange(), "emitDynamicCastToNull"); - return {}; - } + if (dce->isAlwaysNull()) + return emitDynamicCastToNull(*this, loc, destTy); auto destCirTy = mlir::cast<cir::PointerType>(convertType(destTy)); return cgm.getCXXABI().emitDynamicCast(*this, loc, srcRecordTy, destRecordTy, diff --git a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp index f7c4d18..2dce0b1 100644 --- a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp @@ -120,6 +120,8 @@ public: return true; } + void emitBadCastCall(CIRGenFunction &cgf, mlir::Location loc) override; + mlir::Value getVirtualBaseClassOffset(mlir::Location loc, CIRGenFunction &cgf, Address thisAddr, const CXXRecordDecl *classDecl, @@ -1883,6 +1885,11 @@ static void emitCallToBadCast(CIRGenFunction &cgf, mlir::Location loc) { cgf.getBuilder().clearInsertionPoint(); } +void CIRGenItaniumCXXABI::emitBadCastCall(CIRGenFunction &cgf, + mlir::Location loc) { + emitCallToBadCast(cgf, loc); +} + // TODO(cir): This could be shared with classic codegen. static CharUnits computeOffsetHint(ASTContext &astContext, const CXXRecordDecl *src, diff --git a/clang/lib/CIR/CodeGen/CIRGenStmtOpenACC.cpp b/clang/lib/CIR/CodeGen/CIRGenStmtOpenACC.cpp index 77e6f83..349b111 100644 --- a/clang/lib/CIR/CodeGen/CIRGenStmtOpenACC.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenStmtOpenACC.cpp @@ -306,9 +306,10 @@ CIRGenFunction::emitOpenACCCacheConstruct(const OpenACCCacheConstruct &s) { mlir::LogicalResult CIRGenFunction::emitOpenACCAtomicConstruct(const OpenACCAtomicConstruct &s) { - // For now, we are only support 'read', so diagnose. We can switch on the kind - // later once we start implementing the other 3 forms. - if (s.getAtomicKind() != OpenACCAtomicKind::Read) { + // For now, we are only support 'read'/'write', so diagnose. We can switch on + // the kind later once we start implementing the other 2 forms. While we + if (s.getAtomicKind() != OpenACCAtomicKind::Read && + s.getAtomicKind() != OpenACCAtomicKind::Write) { cgm.errorNYI(s.getSourceRange(), "OpenACC Atomic Construct"); return mlir::failure(); } @@ -318,17 +319,41 @@ CIRGenFunction::emitOpenACCAtomicConstruct(const OpenACCAtomicConstruct &s) { // it has custom emit logic. mlir::Location start = getLoc(s.getSourceRange().getBegin()); OpenACCAtomicConstruct::StmtInfo inf = s.getAssociatedStmtInfo(); - // Atomic 'read' only permits 'v = x', where v and x are both scalar L values. - // The getAssociatedStmtInfo strips off implicit casts, which includes - // implicit conversions and L-to-R-Value conversions, so we can just emit it - // as an L value. The Flang implementation has no problem with different - // types, so it appears that the dialect can handle the conversions. - mlir::Value v = emitLValue(inf.V).getPointer(); - mlir::Value x = emitLValue(inf.X).getPointer(); - mlir::Type resTy = convertType(inf.V->getType()); - auto op = mlir::acc::AtomicReadOp::create(builder, start, x, v, resTy, - /*ifCond=*/{}); - emitOpenACCClauses(op, s.getDirectiveKind(), s.getDirectiveLoc(), - s.clauses()); - return mlir::success(); + + switch (s.getAtomicKind()) { + case OpenACCAtomicKind::None: + case OpenACCAtomicKind::Update: + case OpenACCAtomicKind::Capture: + llvm_unreachable("Unimplemented atomic construct type, should have " + "diagnosed/returned above"); + return mlir::failure(); + case OpenACCAtomicKind::Read: { + + // Atomic 'read' only permits 'v = x', where v and x are both scalar L + // values. The getAssociatedStmtInfo strips off implicit casts, which + // includes implicit conversions and L-to-R-Value conversions, so we can + // just emit it as an L value. The Flang implementation has no problem with + // different types, so it appears that the dialect can handle the + // conversions. + mlir::Value v = emitLValue(inf.V).getPointer(); + mlir::Value x = emitLValue(inf.X).getPointer(); + mlir::Type resTy = convertType(inf.V->getType()); + auto op = mlir::acc::AtomicReadOp::create(builder, start, x, v, resTy, + /*ifCond=*/{}); + emitOpenACCClauses(op, s.getDirectiveKind(), s.getDirectiveLoc(), + s.clauses()); + return mlir::success(); + } + case OpenACCAtomicKind::Write: { + mlir::Value x = emitLValue(inf.X).getPointer(); + mlir::Value expr = emitAnyExpr(inf.RefExpr).getValue(); + auto op = mlir::acc::AtomicWriteOp::create(builder, start, x, expr, + /*ifCond=*/{}); + emitOpenACCClauses(op, s.getDirectiveKind(), s.getDirectiveLoc(), + s.clauses()); + return mlir::success(); + } + } + + llvm_unreachable("unknown OpenACC atomic kind"); } diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index a30ae02..5a6193f 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -1695,6 +1695,15 @@ static uint64_t getTypeSize(mlir::Type type, mlir::Operation &op) { return llvm::divideCeil(layout.getTypeSizeInBits(type), 8); } +mlir::LogicalResult CIRToLLVMPrefetchOpLowering::matchAndRewrite( + cir::PrefetchOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const { + rewriter.replaceOpWithNewOp<mlir::LLVM::Prefetch>( + op, adaptor.getAddr(), adaptor.getIsWrite(), adaptor.getLocality(), + /*DataCache=*/1); + return mlir::success(); +} + mlir::LogicalResult CIRToLLVMPtrDiffOpLowering::matchAndRewrite( cir::PtrDiffOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const { diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index c423c4b..468c930 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -684,7 +684,8 @@ static void addKCFIPass(const Triple &TargetTriple, const LangOptions &LangOpts, PassBuilder &PB) { // If the back-end supports KCFI operand bundle lowering, skip KCFIPass. if (TargetTriple.getArch() == llvm::Triple::x86_64 || - TargetTriple.isAArch64(64) || TargetTriple.isRISCV()) + TargetTriple.isAArch64(64) || TargetTriple.isRISCV() || + TargetTriple.isARM() || TargetTriple.isThumb()) return; // Ensure we lower KCFI operand bundles with -O0. diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp index ecab933..945f9e2 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.cpp +++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp @@ -562,17 +562,16 @@ static llvm::Value *createSPIRVBuiltinLoad(IRBuilder<> &B, llvm::Module &M, return B.CreateLoad(Ty, GV); } -llvm::Value * -CGHLSLRuntime::emitSystemSemanticLoad(IRBuilder<> &B, llvm::Type *Type, - const clang::DeclaratorDecl *Decl, - SemanticInfo &ActiveSemantic) { - if (isa<HLSLSV_GroupIndexAttr>(ActiveSemantic.Semantic)) { +llvm::Value *CGHLSLRuntime::emitSystemSemanticLoad( + IRBuilder<> &B, llvm::Type *Type, const clang::DeclaratorDecl *Decl, + Attr *Semantic, std::optional<unsigned> Index) { + if (isa<HLSLSV_GroupIndexAttr>(Semantic)) { llvm::Function *GroupIndex = CGM.getIntrinsic(getFlattenedThreadIdInGroupIntrinsic()); return B.CreateCall(FunctionCallee(GroupIndex)); } - if (isa<HLSLSV_DispatchThreadIDAttr>(ActiveSemantic.Semantic)) { + if (isa<HLSLSV_DispatchThreadIDAttr>(Semantic)) { llvm::Intrinsic::ID IntrinID = getThreadIdIntrinsic(); llvm::Function *ThreadIDIntrinsic = llvm::Intrinsic::isOverloaded(IntrinID) @@ -581,7 +580,7 @@ CGHLSLRuntime::emitSystemSemanticLoad(IRBuilder<> &B, llvm::Type *Type, return buildVectorInput(B, ThreadIDIntrinsic, Type); } - if (isa<HLSLSV_GroupThreadIDAttr>(ActiveSemantic.Semantic)) { + if (isa<HLSLSV_GroupThreadIDAttr>(Semantic)) { llvm::Intrinsic::ID IntrinID = getGroupThreadIdIntrinsic(); llvm::Function *GroupThreadIDIntrinsic = llvm::Intrinsic::isOverloaded(IntrinID) @@ -590,7 +589,7 @@ CGHLSLRuntime::emitSystemSemanticLoad(IRBuilder<> &B, llvm::Type *Type, return buildVectorInput(B, GroupThreadIDIntrinsic, Type); } - if (isa<HLSLSV_GroupIDAttr>(ActiveSemantic.Semantic)) { + if (isa<HLSLSV_GroupIDAttr>(Semantic)) { llvm::Intrinsic::ID IntrinID = getGroupIdIntrinsic(); llvm::Function *GroupIDIntrinsic = llvm::Intrinsic::isOverloaded(IntrinID) @@ -599,8 +598,7 @@ CGHLSLRuntime::emitSystemSemanticLoad(IRBuilder<> &B, llvm::Type *Type, return buildVectorInput(B, GroupIDIntrinsic, Type); } - if (HLSLSV_PositionAttr *S = - dyn_cast<HLSLSV_PositionAttr>(ActiveSemantic.Semantic)) { + if (HLSLSV_PositionAttr *S = dyn_cast<HLSLSV_PositionAttr>(Semantic)) { if (CGM.getTriple().getEnvironment() == Triple::EnvironmentType::Pixel) return createSPIRVBuiltinLoad(B, CGM.getModule(), Type, S->getAttrName()->getName(), @@ -611,29 +609,56 @@ CGHLSLRuntime::emitSystemSemanticLoad(IRBuilder<> &B, llvm::Type *Type, } llvm::Value * -CGHLSLRuntime::handleScalarSemanticLoad(IRBuilder<> &B, llvm::Type *Type, - const clang::DeclaratorDecl *Decl, - SemanticInfo &ActiveSemantic) { - - if (!ActiveSemantic.Semantic) { - ActiveSemantic.Semantic = Decl->getAttr<HLSLSemanticAttr>(); - if (!ActiveSemantic.Semantic) { - CGM.getDiags().Report(Decl->getInnerLocStart(), - diag::err_hlsl_semantic_missing); - return nullptr; +CGHLSLRuntime::handleScalarSemanticLoad(IRBuilder<> &B, const FunctionDecl *FD, + llvm::Type *Type, + const clang::DeclaratorDecl *Decl) { + + HLSLSemanticAttr *Semantic = nullptr; + for (HLSLSemanticAttr *Item : FD->specific_attrs<HLSLSemanticAttr>()) { + if (Item->getTargetDecl() == Decl) { + Semantic = Item; + break; } - ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex(); } + // Sema must create one attribute per scalar field. + assert(Semantic); - return emitSystemSemanticLoad(B, Type, Decl, ActiveSemantic); + std::optional<unsigned> Index = std::nullopt; + if (Semantic->isSemanticIndexExplicit()) + Index = Semantic->getSemanticIndex(); + return emitSystemSemanticLoad(B, Type, Decl, Semantic, Index); } llvm::Value * -CGHLSLRuntime::handleSemanticLoad(IRBuilder<> &B, llvm::Type *Type, - const clang::DeclaratorDecl *Decl, - SemanticInfo &ActiveSemantic) { - assert(!Type->isStructTy()); - return handleScalarSemanticLoad(B, Type, Decl, ActiveSemantic); +CGHLSLRuntime::handleStructSemanticLoad(IRBuilder<> &B, const FunctionDecl *FD, + llvm::Type *Type, + const clang::DeclaratorDecl *Decl) { + const llvm::StructType *ST = cast<StructType>(Type); + const clang::RecordDecl *RD = Decl->getType()->getAsRecordDecl(); + + assert(std::distance(RD->field_begin(), RD->field_end()) == + ST->getNumElements()); + + llvm::Value *Aggregate = llvm::PoisonValue::get(Type); + auto FieldDecl = RD->field_begin(); + for (unsigned I = 0; I < ST->getNumElements(); ++I) { + llvm::Value *ChildValue = + handleSemanticLoad(B, FD, ST->getElementType(I), *FieldDecl); + assert(ChildValue); + Aggregate = B.CreateInsertValue(Aggregate, ChildValue, I); + ++FieldDecl; + } + + return Aggregate; +} + +llvm::Value * +CGHLSLRuntime::handleSemanticLoad(IRBuilder<> &B, const FunctionDecl *FD, + llvm::Type *Type, + const clang::DeclaratorDecl *Decl) { + if (Type->isStructTy()) + return handleStructSemanticLoad(B, FD, Type, Decl); + return handleScalarSemanticLoad(B, FD, Type, Decl); } void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD, @@ -680,8 +705,25 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD, } const ParmVarDecl *PD = FD->getParamDecl(Param.getArgNo() - SRetOffset); - SemanticInfo ActiveSemantic = {nullptr, 0}; - Args.push_back(handleSemanticLoad(B, Param.getType(), PD, ActiveSemantic)); + llvm::Value *SemanticValue = nullptr; + if ([[maybe_unused]] HLSLParamModifierAttr *MA = + PD->getAttr<HLSLParamModifierAttr>()) { + llvm_unreachable("Not handled yet"); + } else { + llvm::Type *ParamType = + Param.hasByValAttr() ? Param.getParamByValType() : Param.getType(); + SemanticValue = handleSemanticLoad(B, FD, ParamType, PD); + if (!SemanticValue) + return; + if (Param.hasByValAttr()) { + llvm::Value *Var = B.CreateAlloca(Param.getParamByValType()); + B.CreateStore(SemanticValue, Var); + SemanticValue = Var; + } + } + + assert(SemanticValue); + Args.push_back(SemanticValue); } CallInst *CI = B.CreateCall(FunctionCallee(Fn), Args, OB); diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h index 103b4a9..d35df52 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.h +++ b/clang/lib/CodeGen/CGHLSLRuntime.h @@ -144,26 +144,24 @@ public: protected: CodeGenModule &CGM; - void collectInputSemantic(llvm::IRBuilder<> &B, const DeclaratorDecl *D, - llvm::Type *Type, - SmallVectorImpl<llvm::Value *> &Inputs); - - struct SemanticInfo { - clang::HLSLSemanticAttr *Semantic; - uint32_t Index; - }; - llvm::Value *emitSystemSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type, const clang::DeclaratorDecl *Decl, - SemanticInfo &ActiveSemantic); - - llvm::Value *handleScalarSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type, - const clang::DeclaratorDecl *Decl, - SemanticInfo &ActiveSemantic); - - llvm::Value *handleSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type, - const clang::DeclaratorDecl *Decl, - SemanticInfo &ActiveSemantic); + Attr *Semantic, + std::optional<unsigned> Index); + + llvm::Value *handleScalarSemanticLoad(llvm::IRBuilder<> &B, + const FunctionDecl *FD, + llvm::Type *Type, + const clang::DeclaratorDecl *Decl); + + llvm::Value *handleStructSemanticLoad(llvm::IRBuilder<> &B, + const FunctionDecl *FD, + llvm::Type *Type, + const clang::DeclaratorDecl *Decl); + + llvm::Value *handleSemanticLoad(llvm::IRBuilder<> &B, const FunctionDecl *FD, + llvm::Type *Type, + const clang::DeclaratorDecl *Decl); public: CGHLSLRuntime(CodeGenModule &CGM) : CGM(CGM) {} diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index 85b2404..66fea92 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -2713,14 +2713,6 @@ llvm::Value *CGOpenMPRuntime::emitMessageClause(CodeGenFunction &CGF, } llvm::Value * -CGOpenMPRuntime::emitMessageClause(CodeGenFunction &CGF, - const OMPMessageClause *MessageClause) { - return emitMessageClause( - CGF, MessageClause ? MessageClause->getMessageString() : nullptr, - MessageClause->getBeginLoc()); -} - -llvm::Value * CGOpenMPRuntime::emitSeverityClause(OpenMPSeverityClauseKind Severity, SourceLocation Loc) { // OpenMP 6.0, 10.4: "If no severity clause is specified then the effect is @@ -2729,13 +2721,6 @@ CGOpenMPRuntime::emitSeverityClause(OpenMPSeverityClauseKind Severity, Severity == OMPC_SEVERITY_warning ? 1 : 2); } -llvm::Value * -CGOpenMPRuntime::emitSeverityClause(const OMPSeverityClause *SeverityClause) { - return emitSeverityClause(SeverityClause ? SeverityClause->getSeverityKind() - : OMPC_SEVERITY_unknown, - SeverityClause->getBeginLoc()); -} - void CGOpenMPRuntime::emitNumThreadsClause( CodeGenFunction &CGF, llvm::Value *NumThreads, SourceLocation Loc, OpenMPNumThreadsClauseModifier Modifier, OpenMPSeverityClauseKind Severity, diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.h b/clang/lib/CodeGen/CGOpenMPRuntime.h index ba76ba6b..6bfd7d6 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.h +++ b/clang/lib/CodeGen/CGOpenMPRuntime.h @@ -1051,13 +1051,9 @@ public: virtual llvm::Value *emitMessageClause(CodeGenFunction &CGF, const Expr *Message, SourceLocation Loc); - virtual llvm::Value *emitMessageClause(CodeGenFunction &CGF, - const OMPMessageClause *MessageClause); virtual llvm::Value *emitSeverityClause(OpenMPSeverityClauseKind Severity, SourceLocation Loc); - virtual llvm::Value * - emitSeverityClause(const OMPSeverityClause *SeverityClause); /// Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 /// global_tid, kmp_int32 num_threads) to generate code for 'num_threads' diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 99400ac..727af69 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -949,6 +949,24 @@ bool tools::isTLSDESCEnabled(const ToolChain &TC, return EnableTLSDESC; } +void tools::addDTLTOOptions(const ToolChain &ToolChain, const ArgList &Args, + llvm::opt::ArgStringList &CmdArgs) { + if (Arg *A = Args.getLastArg(options::OPT_fthinlto_distributor_EQ)) { + CmdArgs.push_back( + Args.MakeArgString("--thinlto-distributor=" + Twine(A->getValue()))); + const Driver &D = ToolChain.getDriver(); + CmdArgs.push_back(Args.MakeArgString("--thinlto-remote-compiler=" + + Twine(D.getClangProgramPath()))); + if (auto *PA = D.getPrependArg()) + CmdArgs.push_back(Args.MakeArgString( + "--thinlto-remote-compiler-prepend-arg=" + Twine(PA))); + + for (const auto &A : + Args.getAllArgValues(options::OPT_Xthinlto_distributor_EQ)) + CmdArgs.push_back(Args.MakeArgString("--thinlto-distributor-arg=" + A)); + } +} + void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args, ArgStringList &CmdArgs, const InputInfo &Output, const InputInfoList &Inputs, bool IsThinLTO) { @@ -1350,16 +1368,7 @@ void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args, CmdArgs.push_back( Args.MakeArgString(Twine(PluginOptPrefix) + "-time-passes")); - if (Arg *A = Args.getLastArg(options::OPT_fthinlto_distributor_EQ)) { - CmdArgs.push_back( - Args.MakeArgString("--thinlto-distributor=" + Twine(A->getValue()))); - CmdArgs.push_back( - Args.MakeArgString("--thinlto-remote-compiler=" + - Twine(ToolChain.getDriver().getClangProgramPath()))); - - for (auto A : Args.getAllArgValues(options::OPT_Xthinlto_distributor_EQ)) - CmdArgs.push_back(Args.MakeArgString("--thinlto-distributor-arg=" + A)); - } + addDTLTOOptions(ToolChain, Args, CmdArgs); } void tools::addOpenMPRuntimeLibraryPath(const ToolChain &TC, diff --git a/clang/lib/Driver/ToolChains/PS4CPU.cpp b/clang/lib/Driver/ToolChains/PS4CPU.cpp index 61afc61..34ec65a 100644 --- a/clang/lib/Driver/ToolChains/PS4CPU.cpp +++ b/clang/lib/Driver/ToolChains/PS4CPU.cpp @@ -344,16 +344,7 @@ void tools::PS5cpu::Linker::ConstructJob(Compilation &C, const JobAction &JA, // pass LTO options to ensure proper codegen, metadata production, etc if // LTO indeed occurs. - if (const Arg *A = Args.getLastArg(options::OPT_fthinlto_distributor_EQ)) { - CmdArgs.push_back( - Args.MakeArgString("--thinlto-distributor=" + Twine(A->getValue()))); - CmdArgs.push_back(Args.MakeArgString("--thinlto-remote-compiler=" + - Twine(D.getClangProgramPath()))); - - for (const auto &A : - Args.getAllArgValues(options::OPT_Xthinlto_distributor_EQ)) - CmdArgs.push_back(Args.MakeArgString("--thinlto-distributor-arg=" + A)); - } + tools::addDTLTOOptions(TC, Args, CmdArgs); if (Args.hasFlag(options::OPT_funified_lto, options::OPT_fno_unified_lto, true)) diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index c97a9e8..1d0dfd0b 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -4407,8 +4407,12 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line, // breaking after it. if (Right.is(TT_SelectorName)) return 0; - if (Left.is(tok::colon) && Left.is(TT_ObjCMethodExpr)) - return Line.MightBeFunctionDecl ? 50 : 500; + if (Left.is(tok::colon)) { + if (Left.is(TT_ObjCMethodExpr)) + return Line.MightBeFunctionDecl ? 50 : 500; + if (Left.is(TT_ObjCSelector)) + return 500; + } // In Objective-C type declarations, avoid breaking after the category's // open paren (we'll prefer breaking after the protocol list's opening @@ -6291,7 +6295,9 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line, TT_BitFieldColon)) { return false; } - if (Left.is(tok::colon) && Left.isOneOf(TT_DictLiteral, TT_ObjCMethodExpr)) { + if (Left.is(tok::colon) && Left.isOneOf(TT_ObjCSelector, TT_ObjCMethodExpr)) + return true; + if (Left.is(tok::colon) && Left.is(TT_DictLiteral)) { if (Style.isProto()) { if (!Style.AlwaysBreakBeforeMultilineStrings && Right.isStringLiteral()) return false; diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index 374138f..e3bf0ea 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -546,14 +546,11 @@ void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) { std::string CompilerInstance::getSpecificModuleCachePath(StringRef ModuleHash) { assert(FileMgr && "Specific module cache path requires a FileManager"); - if (getHeaderSearchOpts().ModuleCachePath.empty()) - return ""; - // Set up the module path, including the hash for the module-creation options. SmallString<256> SpecificModuleCache; normalizeModuleCachePath(*FileMgr, getHeaderSearchOpts().ModuleCachePath, SpecificModuleCache); - if (!getHeaderSearchOpts().DisableModuleHash) + if (!SpecificModuleCache.empty() && !getHeaderSearchOpts().DisableModuleHash) llvm::sys::path::append(SpecificModuleCache, ModuleHash); return std::string(SpecificModuleCache); } diff --git a/clang/lib/Headers/CMakeLists.txt b/clang/lib/Headers/CMakeLists.txt index 32a6be8..1858912 100644 --- a/clang/lib/Headers/CMakeLists.txt +++ b/clang/lib/Headers/CMakeLists.txt @@ -4,6 +4,9 @@ set(core_files builtins.h float.h + __float_float.h + __float_header_macro.h + __float_infinity_nan.h inttypes.h iso646.h limits.h diff --git a/clang/lib/Headers/__float_float.h b/clang/lib/Headers/__float_float.h new file mode 100644 index 0000000..267c072 --- /dev/null +++ b/clang/lib/Headers/__float_float.h @@ -0,0 +1,176 @@ +/*===---- __float_float.h --------------------------------------------------=== + * + * 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 + * + *===-----------------------------------------------------------------------=== + */ + +#ifndef __CLANG_FLOAT_FLOAT_H +#define __CLANG_FLOAT_FLOAT_H + +#if (defined(__MINGW32__) || defined(_MSC_VER) || defined(_AIX)) && \ + __STDC_HOSTED__ + +/* Undefine anything that we'll be redefining below. */ +# undef FLT_EVAL_METHOD +# undef FLT_ROUNDS +# undef FLT_RADIX +# undef FLT_MANT_DIG +# undef DBL_MANT_DIG +# undef LDBL_MANT_DIG +#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \ + !defined(__STRICT_ANSI__) || \ + (defined(__cplusplus) && __cplusplus >= 201103L) || \ + (__STDC_HOSTED__ && defined(_AIX) && defined(_ALL_SOURCE)) +# undef DECIMAL_DIG +# endif +# undef FLT_DIG +# undef DBL_DIG +# undef LDBL_DIG +# undef FLT_MIN_EXP +# undef DBL_MIN_EXP +# undef LDBL_MIN_EXP +# undef FLT_MIN_10_EXP +# undef DBL_MIN_10_EXP +# undef LDBL_MIN_10_EXP +# undef FLT_MAX_EXP +# undef DBL_MAX_EXP +# undef LDBL_MAX_EXP +# undef FLT_MAX_10_EXP +# undef DBL_MAX_10_EXP +# undef LDBL_MAX_10_EXP +# undef FLT_MAX +# undef DBL_MAX +# undef LDBL_MAX +# undef FLT_EPSILON +# undef DBL_EPSILON +# undef LDBL_EPSILON +# undef FLT_MIN +# undef DBL_MIN +# undef LDBL_MIN +#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) || \ + !defined(__STRICT_ANSI__) || \ + (defined(__cplusplus) && __cplusplus >= 201703L) || \ + (__STDC_HOSTED__ && defined(_AIX) && defined(_ALL_SOURCE)) +# undef FLT_TRUE_MIN +# undef DBL_TRUE_MIN +# undef LDBL_TRUE_MIN +# undef FLT_DECIMAL_DIG +# undef DBL_DECIMAL_DIG +# undef LDBL_DECIMAL_DIG +# undef FLT_HAS_SUBNORM +# undef DBL_HAS_SUBNORM +# undef LDBL_HAS_SUBNORM +# endif +#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) || \ + !defined(__STRICT_ANSI__) +# undef FLT_NORM_MAX +# undef DBL_NORM_MAX +# undef LDBL_NORM_MAX +#endif +#endif + +#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) || \ + !defined(__STRICT_ANSI__) +# undef FLT_SNAN +# undef DBL_SNAN +# undef LDBL_SNAN +#endif + +/* Characteristics of floating point types, C99 5.2.4.2.2 */ + +#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \ + (defined(__cplusplus) && __cplusplus >= 201103L) +#define FLT_EVAL_METHOD __FLT_EVAL_METHOD__ +#endif +#define FLT_ROUNDS (__builtin_flt_rounds()) +#define FLT_RADIX __FLT_RADIX__ + +#define FLT_MANT_DIG __FLT_MANT_DIG__ +#define DBL_MANT_DIG __DBL_MANT_DIG__ +#define LDBL_MANT_DIG __LDBL_MANT_DIG__ + +#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \ + !defined(__STRICT_ANSI__) || \ + (defined(__cplusplus) && __cplusplus >= 201103L) || \ + (__STDC_HOSTED__ && defined(_AIX) && defined(_ALL_SOURCE)) +# define DECIMAL_DIG __DECIMAL_DIG__ +#endif + +#define FLT_DIG __FLT_DIG__ +#define DBL_DIG __DBL_DIG__ +#define LDBL_DIG __LDBL_DIG__ + +#define FLT_MIN_EXP __FLT_MIN_EXP__ +#define DBL_MIN_EXP __DBL_MIN_EXP__ +#define LDBL_MIN_EXP __LDBL_MIN_EXP__ + +#define FLT_MIN_10_EXP __FLT_MIN_10_EXP__ +#define DBL_MIN_10_EXP __DBL_MIN_10_EXP__ +#define LDBL_MIN_10_EXP __LDBL_MIN_10_EXP__ + +#define FLT_MAX_EXP __FLT_MAX_EXP__ +#define DBL_MAX_EXP __DBL_MAX_EXP__ +#define LDBL_MAX_EXP __LDBL_MAX_EXP__ + +#define FLT_MAX_10_EXP __FLT_MAX_10_EXP__ +#define DBL_MAX_10_EXP __DBL_MAX_10_EXP__ +#define LDBL_MAX_10_EXP __LDBL_MAX_10_EXP__ + +#define FLT_MAX __FLT_MAX__ +#define DBL_MAX __DBL_MAX__ +#define LDBL_MAX __LDBL_MAX__ + +#define FLT_EPSILON __FLT_EPSILON__ +#define DBL_EPSILON __DBL_EPSILON__ +#define LDBL_EPSILON __LDBL_EPSILON__ + +#define FLT_MIN __FLT_MIN__ +#define DBL_MIN __DBL_MIN__ +#define LDBL_MIN __LDBL_MIN__ + +#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) || \ + !defined(__STRICT_ANSI__) || \ + (defined(__cplusplus) && __cplusplus >= 201703L) || \ + (__STDC_HOSTED__ && defined(_AIX) && defined(_ALL_SOURCE)) +# define FLT_TRUE_MIN __FLT_DENORM_MIN__ +# define DBL_TRUE_MIN __DBL_DENORM_MIN__ +# define LDBL_TRUE_MIN __LDBL_DENORM_MIN__ +# define FLT_DECIMAL_DIG __FLT_DECIMAL_DIG__ +# define DBL_DECIMAL_DIG __DBL_DECIMAL_DIG__ +# define LDBL_DECIMAL_DIG __LDBL_DECIMAL_DIG__ +# define FLT_HAS_SUBNORM __FLT_HAS_DENORM__ +# define DBL_HAS_SUBNORM __DBL_HAS_DENORM__ +# define LDBL_HAS_SUBNORM __LDBL_HAS_DENORM__ +#endif + +#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) || \ + !defined(__STRICT_ANSI__) + /* C23 5.2.5.3.2p28 */ +# define FLT_SNAN (__builtin_nansf("")) +# define DBL_SNAN (__builtin_nans("")) +# define LDBL_SNAN (__builtin_nansl("")) + + /* C23 5.2.5.3.3p32 */ +# define FLT_NORM_MAX __FLT_NORM_MAX__ +# define DBL_NORM_MAX __DBL_NORM_MAX__ +# define LDBL_NORM_MAX __LDBL_NORM_MAX__ +#endif + +#ifdef __STDC_WANT_IEC_60559_TYPES_EXT__ +# define FLT16_MANT_DIG __FLT16_MANT_DIG__ +# define FLT16_DECIMAL_DIG __FLT16_DECIMAL_DIG__ +# define FLT16_DIG __FLT16_DIG__ +# define FLT16_MIN_EXP __FLT16_MIN_EXP__ +# define FLT16_MIN_10_EXP __FLT16_MIN_10_EXP__ +# define FLT16_MAX_EXP __FLT16_MAX_EXP__ +# define FLT16_MAX_10_EXP __FLT16_MAX_10_EXP__ +# define FLT16_MAX __FLT16_MAX__ +# define FLT16_EPSILON __FLT16_EPSILON__ +# define FLT16_MIN __FLT16_MIN__ +# define FLT16_TRUE_MIN __FLT16_TRUE_MIN__ +#endif /* __STDC_WANT_IEC_60559_TYPES_EXT__ */ + +#endif /* __CLANG_FLOAT_FLOAT_H */ diff --git a/clang/lib/Headers/__float_header_macro.h b/clang/lib/Headers/__float_header_macro.h new file mode 100644 index 0000000..11b270e --- /dev/null +++ b/clang/lib/Headers/__float_header_macro.h @@ -0,0 +1,12 @@ +/*===---- __float_header_macro.h -------------------------------------------=== + * + * 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 + * + *===-----------------------------------------------------------------------=== + */ + +#ifndef __CLANG_FLOAT_H +#define __CLANG_FLOAT_H +#endif /* __CLANG_FLOAT_H */ diff --git a/clang/lib/Headers/__float_infinity_nan.h b/clang/lib/Headers/__float_infinity_nan.h new file mode 100644 index 0000000..7e253d0 --- /dev/null +++ b/clang/lib/Headers/__float_infinity_nan.h @@ -0,0 +1,20 @@ +/*===---- __float_infinity_nan.h -------------------------------------------=== + * + * 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 + * + *===-----------------------------------------------------------------------=== + */ + +#ifndef __CLANG_FLOAT_INFINITY_NAN_H +#define __CLANG_FLOAT_INFINITY_NAN_H + +/* C23 5.2.5.3.3p29-30 */ +#undef INFINITY +#undef NAN + +#define INFINITY (__builtin_inff()) +#define NAN (__builtin_nanf("")) + +#endif /* __CLANG_FLOAT_INFINITY_NAN_H */ diff --git a/clang/lib/Headers/avx2intrin.h b/clang/lib/Headers/avx2intrin.h index fdb825f..3cbaaec 100644 --- a/clang/lib/Headers/avx2intrin.h +++ b/clang/lib/Headers/avx2intrin.h @@ -1975,10 +1975,9 @@ _mm256_shuffle_epi8(__m256i __a, __m256i __b) { /// \param __b /// A 256-bit integer vector]. /// \returns A 256-bit integer vector containing the result. -static __inline__ __m256i __DEFAULT_FN_ATTRS256 -_mm256_sign_epi8(__m256i __a, __m256i __b) -{ - return (__m256i)__builtin_ia32_psignb256((__v32qi)__a, (__v32qi)__b); +static __inline__ __m256i __DEFAULT_FN_ATTRS256_CONSTEXPR +_mm256_sign_epi8(__m256i __a, __m256i __b) { + return (__m256i)__builtin_ia32_psignb256((__v32qi)__a, (__v32qi)__b); } /// Sets each element of the result to the corresponding element of the @@ -1996,10 +1995,9 @@ _mm256_sign_epi8(__m256i __a, __m256i __b) /// \param __b /// A 256-bit vector of [16 x i16]. /// \returns A 256-bit vector of [16 x i16] containing the result. -static __inline__ __m256i __DEFAULT_FN_ATTRS256 -_mm256_sign_epi16(__m256i __a, __m256i __b) -{ - return (__m256i)__builtin_ia32_psignw256((__v16hi)__a, (__v16hi)__b); +static __inline__ __m256i __DEFAULT_FN_ATTRS256_CONSTEXPR +_mm256_sign_epi16(__m256i __a, __m256i __b) { + return (__m256i)__builtin_ia32_psignw256((__v16hi)__a, (__v16hi)__b); } /// Sets each element of the result to the corresponding element of the @@ -2017,10 +2015,9 @@ _mm256_sign_epi16(__m256i __a, __m256i __b) /// \param __b /// A 256-bit vector of [8 x i32]. /// \returns A 256-bit vector of [8 x i32] containing the result. -static __inline__ __m256i __DEFAULT_FN_ATTRS256 -_mm256_sign_epi32(__m256i __a, __m256i __b) -{ - return (__m256i)__builtin_ia32_psignd256((__v8si)__a, (__v8si)__b); +static __inline__ __m256i __DEFAULT_FN_ATTRS256_CONSTEXPR +_mm256_sign_epi32(__m256i __a, __m256i __b) { + return (__m256i)__builtin_ia32_psignd256((__v8si)__a, (__v8si)__b); } /// Shifts each 128-bit half of the 256-bit integer vector \a a left by diff --git a/clang/lib/Headers/float.h b/clang/lib/Headers/float.h index 30427c2..82974f6 100644 --- a/clang/lib/Headers/float.h +++ b/clang/lib/Headers/float.h @@ -7,13 +7,21 @@ *===-----------------------------------------------------------------------=== */ -#ifndef __CLANG_FLOAT_H -#define __CLANG_FLOAT_H - #if defined(__MVS__) && __has_include_next(<float.h>) +#include <__float_header_macro.h> #include_next <float.h> #else +#if !defined(__need_infinity_nan) +#define __need_float_float +#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) || \ + !defined(__STRICT_ANSI__) +#define __need_infinity_nan +#endif +#include <__float_header_macro.h> +#endif + +#ifdef __need_float_float /* If we're on MinGW, fall back to the system's float.h, which might have * additional definitions provided for Windows. * For more details see http://msdn.microsoft.com/en-us/library/y0ybw9fy.aspx @@ -26,171 +34,15 @@ # include_next <float.h> -/* Undefine anything that we'll be redefining below. */ -# undef FLT_EVAL_METHOD -# undef FLT_ROUNDS -# undef FLT_RADIX -# undef FLT_MANT_DIG -# undef DBL_MANT_DIG -# undef LDBL_MANT_DIG -#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \ - !defined(__STRICT_ANSI__) || \ - (defined(__cplusplus) && __cplusplus >= 201103L) || \ - (__STDC_HOSTED__ && defined(_AIX) && defined(_ALL_SOURCE)) -# undef DECIMAL_DIG -# endif -# undef FLT_DIG -# undef DBL_DIG -# undef LDBL_DIG -# undef FLT_MIN_EXP -# undef DBL_MIN_EXP -# undef LDBL_MIN_EXP -# undef FLT_MIN_10_EXP -# undef DBL_MIN_10_EXP -# undef LDBL_MIN_10_EXP -# undef FLT_MAX_EXP -# undef DBL_MAX_EXP -# undef LDBL_MAX_EXP -# undef FLT_MAX_10_EXP -# undef DBL_MAX_10_EXP -# undef LDBL_MAX_10_EXP -# undef FLT_MAX -# undef DBL_MAX -# undef LDBL_MAX -# undef FLT_EPSILON -# undef DBL_EPSILON -# undef LDBL_EPSILON -# undef FLT_MIN -# undef DBL_MIN -# undef LDBL_MIN -#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) || \ - !defined(__STRICT_ANSI__) || \ - (defined(__cplusplus) && __cplusplus >= 201703L) || \ - (__STDC_HOSTED__ && defined(_AIX) && defined(_ALL_SOURCE)) -# undef FLT_TRUE_MIN -# undef DBL_TRUE_MIN -# undef LDBL_TRUE_MIN -# undef FLT_DECIMAL_DIG -# undef DBL_DECIMAL_DIG -# undef LDBL_DECIMAL_DIG -# undef FLT_HAS_SUBNORM -# undef DBL_HAS_SUBNORM -# undef LDBL_HAS_SUBNORM -# endif -#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) || \ - !defined(__STRICT_ANSI__) -# undef FLT_NORM_MAX -# undef DBL_NORM_MAX -# undef LDBL_NORM_MAX -#endif -#endif - -#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) || \ - !defined(__STRICT_ANSI__) -# undef INFINITY -# undef NAN -# undef FLT_SNAN -# undef DBL_SNAN -# undef LDBL_SNAN -#endif - -/* Characteristics of floating point types, C99 5.2.4.2.2 */ - -#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \ - (defined(__cplusplus) && __cplusplus >= 201103L) -#define FLT_EVAL_METHOD __FLT_EVAL_METHOD__ #endif -#define FLT_ROUNDS (__builtin_flt_rounds()) -#define FLT_RADIX __FLT_RADIX__ -#define FLT_MANT_DIG __FLT_MANT_DIG__ -#define DBL_MANT_DIG __DBL_MANT_DIG__ -#define LDBL_MANT_DIG __LDBL_MANT_DIG__ - -#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \ - !defined(__STRICT_ANSI__) || \ - (defined(__cplusplus) && __cplusplus >= 201103L) || \ - (__STDC_HOSTED__ && defined(_AIX) && defined(_ALL_SOURCE)) -# define DECIMAL_DIG __DECIMAL_DIG__ -#endif - -#define FLT_DIG __FLT_DIG__ -#define DBL_DIG __DBL_DIG__ -#define LDBL_DIG __LDBL_DIG__ - -#define FLT_MIN_EXP __FLT_MIN_EXP__ -#define DBL_MIN_EXP __DBL_MIN_EXP__ -#define LDBL_MIN_EXP __LDBL_MIN_EXP__ - -#define FLT_MIN_10_EXP __FLT_MIN_10_EXP__ -#define DBL_MIN_10_EXP __DBL_MIN_10_EXP__ -#define LDBL_MIN_10_EXP __LDBL_MIN_10_EXP__ - -#define FLT_MAX_EXP __FLT_MAX_EXP__ -#define DBL_MAX_EXP __DBL_MAX_EXP__ -#define LDBL_MAX_EXP __LDBL_MAX_EXP__ - -#define FLT_MAX_10_EXP __FLT_MAX_10_EXP__ -#define DBL_MAX_10_EXP __DBL_MAX_10_EXP__ -#define LDBL_MAX_10_EXP __LDBL_MAX_10_EXP__ - -#define FLT_MAX __FLT_MAX__ -#define DBL_MAX __DBL_MAX__ -#define LDBL_MAX __LDBL_MAX__ - -#define FLT_EPSILON __FLT_EPSILON__ -#define DBL_EPSILON __DBL_EPSILON__ -#define LDBL_EPSILON __LDBL_EPSILON__ - -#define FLT_MIN __FLT_MIN__ -#define DBL_MIN __DBL_MIN__ -#define LDBL_MIN __LDBL_MIN__ - -#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) || \ - !defined(__STRICT_ANSI__) || \ - (defined(__cplusplus) && __cplusplus >= 201703L) || \ - (__STDC_HOSTED__ && defined(_AIX) && defined(_ALL_SOURCE)) -# define FLT_TRUE_MIN __FLT_DENORM_MIN__ -# define DBL_TRUE_MIN __DBL_DENORM_MIN__ -# define LDBL_TRUE_MIN __LDBL_DENORM_MIN__ -# define FLT_DECIMAL_DIG __FLT_DECIMAL_DIG__ -# define DBL_DECIMAL_DIG __DBL_DECIMAL_DIG__ -# define LDBL_DECIMAL_DIG __LDBL_DECIMAL_DIG__ -# define FLT_HAS_SUBNORM __FLT_HAS_DENORM__ -# define DBL_HAS_SUBNORM __DBL_HAS_DENORM__ -# define LDBL_HAS_SUBNORM __LDBL_HAS_DENORM__ +#include <__float_float.h> +#undef __need_float_float #endif -#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) || \ - !defined(__STRICT_ANSI__) - /* C23 5.2.5.3.2p28 */ -# define FLT_SNAN (__builtin_nansf("")) -# define DBL_SNAN (__builtin_nans("")) -# define LDBL_SNAN (__builtin_nansl("")) - - /* C23 5.2.5.3.3p29-30 */ -# define INFINITY (__builtin_inff()) -# define NAN (__builtin_nanf("")) - - /* C23 5.2.5.3.3p32 */ -# define FLT_NORM_MAX __FLT_NORM_MAX__ -# define DBL_NORM_MAX __DBL_NORM_MAX__ -# define LDBL_NORM_MAX __LDBL_NORM_MAX__ +#ifdef __need_infinity_nan +#include <__float_infinity_nan.h> +#undef __need_infinity_nan #endif -#ifdef __STDC_WANT_IEC_60559_TYPES_EXT__ -# define FLT16_MANT_DIG __FLT16_MANT_DIG__ -# define FLT16_DECIMAL_DIG __FLT16_DECIMAL_DIG__ -# define FLT16_DIG __FLT16_DIG__ -# define FLT16_MIN_EXP __FLT16_MIN_EXP__ -# define FLT16_MIN_10_EXP __FLT16_MIN_10_EXP__ -# define FLT16_MAX_EXP __FLT16_MAX_EXP__ -# define FLT16_MAX_10_EXP __FLT16_MAX_10_EXP__ -# define FLT16_MAX __FLT16_MAX__ -# define FLT16_EPSILON __FLT16_EPSILON__ -# define FLT16_MIN __FLT16_MIN__ -# define FLT16_TRUE_MIN __FLT16_TRUE_MIN__ -#endif /* __STDC_WANT_IEC_60559_TYPES_EXT__ */ - #endif /* __MVS__ */ -#endif /* __CLANG_FLOAT_H */ diff --git a/clang/lib/Headers/module.modulemap b/clang/lib/Headers/module.modulemap index bdf5119..2e4d533 100644 --- a/clang/lib/Headers/module.modulemap +++ b/clang/lib/Headers/module.modulemap @@ -171,8 +171,22 @@ module _Builtin_intrinsics [system] [extern_c] { // that module. The system float.h (if present) will be treated // as a textual header in the sytem module. module _Builtin_float [system] { - header "float.h" - export * + textual header "float.h" + + explicit module float { + header "__float_float.h" + export * + } + + explicit module header_macro { + header "__float_header_macro.h" + export * + } + + explicit module infinity_nan { + header "__float_infinity_nan.h" + export * + } } module _Builtin_inttypes [system] { diff --git a/clang/lib/Headers/tmmintrin.h b/clang/lib/Headers/tmmintrin.h index 5d0f20f..cb4b36e 100644 --- a/clang/lib/Headers/tmmintrin.h +++ b/clang/lib/Headers/tmmintrin.h @@ -26,9 +26,6 @@ #define __zext128(x) \ (__m128i) __builtin_shufflevector((__v2si)(x), __extension__(__v2si){}, 0, \ 1, 2, 3) -#define __anyext128(x) \ - (__m128i) __builtin_shufflevector((__v2si)(x), __extension__(__v2si){}, 0, \ - 1, -1, -1) #if defined(__cplusplus) && (__cplusplus >= 201103L) #define __DEFAULT_FN_ATTRS_CONSTEXPR __DEFAULT_FN_ATTRS constexpr @@ -641,10 +638,9 @@ _mm_shuffle_pi8(__m64 __a, __m64 __b) { /// A 128-bit integer vector containing control bytes corresponding to /// positions in the destination. /// \returns A 128-bit integer vector containing the resultant values. -static __inline__ __m128i __DEFAULT_FN_ATTRS -_mm_sign_epi8(__m128i __a, __m128i __b) -{ - return (__m128i)__builtin_ia32_psignb128((__v16qi)__a, (__v16qi)__b); +static __inline__ __m128i __DEFAULT_FN_ATTRS_CONSTEXPR +_mm_sign_epi8(__m128i __a, __m128i __b) { + return (__m128i)__builtin_ia32_psignb128((__v16qi)__a, (__v16qi)__b); } /// For each 16-bit integer in the first source operand, perform one of @@ -667,10 +663,9 @@ _mm_sign_epi8(__m128i __a, __m128i __b) /// A 128-bit integer vector containing control words corresponding to /// positions in the destination. /// \returns A 128-bit integer vector containing the resultant values. -static __inline__ __m128i __DEFAULT_FN_ATTRS -_mm_sign_epi16(__m128i __a, __m128i __b) -{ - return (__m128i)__builtin_ia32_psignw128((__v8hi)__a, (__v8hi)__b); +static __inline__ __m128i __DEFAULT_FN_ATTRS_CONSTEXPR +_mm_sign_epi16(__m128i __a, __m128i __b) { + return (__m128i)__builtin_ia32_psignw128((__v8hi)__a, (__v8hi)__b); } /// For each 32-bit integer in the first source operand, perform one of @@ -693,10 +688,9 @@ _mm_sign_epi16(__m128i __a, __m128i __b) /// A 128-bit integer vector containing control doublewords corresponding to /// positions in the destination. /// \returns A 128-bit integer vector containing the resultant values. -static __inline__ __m128i __DEFAULT_FN_ATTRS -_mm_sign_epi32(__m128i __a, __m128i __b) -{ - return (__m128i)__builtin_ia32_psignd128((__v4si)__a, (__v4si)__b); +static __inline__ __m128i __DEFAULT_FN_ATTRS_CONSTEXPR +_mm_sign_epi32(__m128i __a, __m128i __b) { + return (__m128i)__builtin_ia32_psignd128((__v4si)__a, (__v4si)__b); } /// For each 8-bit integer in the first source operand, perform one of @@ -719,11 +713,10 @@ _mm_sign_epi32(__m128i __a, __m128i __b) /// A 64-bit integer vector containing control bytes corresponding to /// positions in the destination. /// \returns A 64-bit integer vector containing the resultant values. -static __inline__ __m64 __DEFAULT_FN_ATTRS -_mm_sign_pi8(__m64 __a, __m64 __b) -{ - return __trunc64(__builtin_ia32_psignb128((__v16qi)__anyext128(__a), - (__v16qi)__anyext128(__b))); +static __inline__ __m64 __DEFAULT_FN_ATTRS_CONSTEXPR _mm_sign_pi8(__m64 __a, + __m64 __b) { + return __trunc64(__builtin_ia32_psignb128((__v16qi)__zext128(__a), + (__v16qi)__zext128(__b))); } /// For each 16-bit integer in the first source operand, perform one of @@ -746,11 +739,10 @@ _mm_sign_pi8(__m64 __a, __m64 __b) /// A 64-bit integer vector containing control words corresponding to /// positions in the destination. /// \returns A 64-bit integer vector containing the resultant values. -static __inline__ __m64 __DEFAULT_FN_ATTRS -_mm_sign_pi16(__m64 __a, __m64 __b) -{ - return __trunc64(__builtin_ia32_psignw128((__v8hi)__anyext128(__a), - (__v8hi)__anyext128(__b))); +static __inline__ __m64 __DEFAULT_FN_ATTRS_CONSTEXPR _mm_sign_pi16(__m64 __a, + __m64 __b) { + return __trunc64( + __builtin_ia32_psignw128((__v8hi)__zext128(__a), (__v8hi)__zext128(__b))); } /// For each 32-bit integer in the first source operand, perform one of @@ -773,14 +765,12 @@ _mm_sign_pi16(__m64 __a, __m64 __b) /// A 64-bit integer vector containing two control doublewords corresponding /// to positions in the destination. /// \returns A 64-bit integer vector containing the resultant values. -static __inline__ __m64 __DEFAULT_FN_ATTRS -_mm_sign_pi32(__m64 __a, __m64 __b) -{ - return __trunc64(__builtin_ia32_psignd128((__v4si)__anyext128(__a), - (__v4si)__anyext128(__b))); +static __inline__ __m64 __DEFAULT_FN_ATTRS_CONSTEXPR _mm_sign_pi32(__m64 __a, + __m64 __b) { + return __trunc64( + __builtin_ia32_psignd128((__v4si)__zext128(__a), (__v4si)__zext128(__b))); } -#undef __anyext128 #undef __zext128 #undef __trunc64 #undef __DEFAULT_FN_ATTRS diff --git a/clang/lib/Lex/HeaderSearch.cpp b/clang/lib/Lex/HeaderSearch.cpp index 238c5e2..65c324c 100644 --- a/clang/lib/Lex/HeaderSearch.cpp +++ b/clang/lib/Lex/HeaderSearch.cpp @@ -2186,6 +2186,8 @@ std::string HeaderSearch::suggestPathToFileForDiagnostics( void clang::normalizeModuleCachePath(FileManager &FileMgr, StringRef Path, SmallVectorImpl<char> &NormalizedPath) { NormalizedPath.assign(Path.begin(), Path.end()); - FileMgr.makeAbsolutePath(NormalizedPath); - llvm::sys::path::remove_dots(NormalizedPath); + if (!NormalizedPath.empty()) { + FileMgr.makeAbsolutePath(NormalizedPath); + llvm::sys::path::remove_dots(NormalizedPath); + } } diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 2990fd6..f99c01e 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -1498,6 +1498,24 @@ static void builtinAllocaAddrSpace(Sema &S, CallExpr *TheCall) { TheCall->setType(S.Context.getPointerType(RT)); } +static bool checkBuiltinInferAllocToken(Sema &S, CallExpr *TheCall) { + if (S.checkArgCountAtLeast(TheCall, 1)) + return true; + + for (Expr *Arg : TheCall->arguments()) { + // If argument is dependent on a template parameter, we can't resolve now. + if (Arg->isTypeDependent() || Arg->isValueDependent()) + continue; + // Reject void types. + QualType ArgTy = Arg->IgnoreParenImpCasts()->getType(); + if (ArgTy->isVoidType()) + return S.Diag(Arg->getBeginLoc(), diag::err_param_with_void_type); + } + + TheCall->setType(S.Context.UnsignedLongLongTy); + return false; +} + namespace { enum PointerAuthOpKind { PAO_Strip, @@ -2779,6 +2797,10 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, builtinAllocaAddrSpace(*this, TheCall); } break; + case Builtin::BI__builtin_infer_alloc_token: + if (checkBuiltinInferAllocToken(*this, TheCall)) + return ExprError(); + break; case Builtin::BI__arithmetic_fence: if (BuiltinArithmeticFence(TheCall)) return ExprError(); diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index 5b3e89f..2a485da 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -770,23 +770,81 @@ void SemaHLSL::ActOnTopLevelFunction(FunctionDecl *FD) { } } -bool SemaHLSL::isSemanticValid(FunctionDecl *FD, DeclaratorDecl *D) { - const auto *AnnotationAttr = D->getAttr<HLSLAnnotationAttr>(); - if (AnnotationAttr) { - CheckSemanticAnnotation(FD, D, AnnotationAttr); - return true; +HLSLSemanticAttr *SemaHLSL::createSemantic(const SemanticInfo &Info, + DeclaratorDecl *TargetDecl) { + std::string SemanticName = Info.Semantic->getAttrName()->getName().upper(); + + if (SemanticName == "SV_DISPATCHTHREADID") { + return createSemanticAttr<HLSLSV_DispatchThreadIDAttr>( + *Info.Semantic, TargetDecl, Info.Index); + } else if (SemanticName == "SV_GROUPINDEX") { + return createSemanticAttr<HLSLSV_GroupIndexAttr>(*Info.Semantic, TargetDecl, + Info.Index); + } else if (SemanticName == "SV_GROUPTHREADID") { + return createSemanticAttr<HLSLSV_GroupThreadIDAttr>(*Info.Semantic, + TargetDecl, Info.Index); + } else if (SemanticName == "SV_GROUPID") { + return createSemanticAttr<HLSLSV_GroupIDAttr>(*Info.Semantic, TargetDecl, + Info.Index); + } else if (SemanticName == "SV_POSITION") { + return createSemanticAttr<HLSLSV_PositionAttr>(*Info.Semantic, TargetDecl, + Info.Index); + } else + Diag(Info.Semantic->getLoc(), diag::err_hlsl_unknown_semantic) + << *Info.Semantic; + + return nullptr; +} + +bool SemaHLSL::determineActiveSemanticOnScalar(FunctionDecl *FD, + DeclaratorDecl *D, + SemanticInfo &ActiveSemantic) { + if (ActiveSemantic.Semantic == nullptr) { + ActiveSemantic.Semantic = D->getAttr<HLSLSemanticAttr>(); + if (ActiveSemantic.Semantic && + ActiveSemantic.Semantic->isSemanticIndexExplicit()) + ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex(); + } + + if (!ActiveSemantic.Semantic) { + Diag(D->getLocation(), diag::err_hlsl_missing_semantic_annotation); + return false; + } + + auto *A = createSemantic(ActiveSemantic, D); + if (!A) + return false; + + checkSemanticAnnotation(FD, D, A); + FD->addAttr(A); + return true; +} + +bool SemaHLSL::determineActiveSemantic(FunctionDecl *FD, DeclaratorDecl *D, + SemanticInfo &ActiveSemantic) { + if (ActiveSemantic.Semantic == nullptr) { + ActiveSemantic.Semantic = D->getAttr<HLSLSemanticAttr>(); + if (ActiveSemantic.Semantic && + ActiveSemantic.Semantic->isSemanticIndexExplicit()) + ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex(); } const Type *T = D->getType()->getUnqualifiedDesugaredType(); const RecordType *RT = dyn_cast<RecordType>(T); if (!RT) - return false; + return determineActiveSemanticOnScalar(FD, D, ActiveSemantic); const RecordDecl *RD = RT->getDecl(); for (FieldDecl *Field : RD->fields()) { - if (!isSemanticValid(FD, Field)) + SemanticInfo Info = ActiveSemantic; + if (!determineActiveSemantic(FD, Field, Info)) { + Diag(Field->getLocation(), diag::note_hlsl_semantic_used_here) << Field; return false; + } + if (ActiveSemantic.Semantic) + ActiveSemantic = Info; } + return true; } @@ -853,8 +911,11 @@ void SemaHLSL::CheckEntryPoint(FunctionDecl *FD) { } for (ParmVarDecl *Param : FD->parameters()) { - if (!isSemanticValid(FD, Param)) { - Diag(FD->getLocation(), diag::err_hlsl_missing_semantic_annotation); + SemanticInfo ActiveSemantic; + ActiveSemantic.Semantic = nullptr; + ActiveSemantic.Index = std::nullopt; + + if (!determineActiveSemantic(FD, Param, ActiveSemantic)) { Diag(Param->getLocation(), diag::note_previous_decl) << Param; FD->setInvalidDecl(); } @@ -862,31 +923,31 @@ void SemaHLSL::CheckEntryPoint(FunctionDecl *FD) { // FIXME: Verify return type semantic annotation. } -void SemaHLSL::CheckSemanticAnnotation( - FunctionDecl *EntryPoint, const Decl *Param, - const HLSLAnnotationAttr *AnnotationAttr) { +void SemaHLSL::checkSemanticAnnotation(FunctionDecl *EntryPoint, + const Decl *Param, + const HLSLSemanticAttr *SemanticAttr) { auto *ShaderAttr = EntryPoint->getAttr<HLSLShaderAttr>(); assert(ShaderAttr && "Entry point has no shader attribute"); llvm::Triple::EnvironmentType ST = ShaderAttr->getType(); - switch (AnnotationAttr->getKind()) { + switch (SemanticAttr->getKind()) { case attr::HLSLSV_DispatchThreadID: case attr::HLSLSV_GroupIndex: case attr::HLSLSV_GroupThreadID: case attr::HLSLSV_GroupID: if (ST == llvm::Triple::Compute) return; - DiagnoseAttrStageMismatch(AnnotationAttr, ST, {llvm::Triple::Compute}); + DiagnoseAttrStageMismatch(SemanticAttr, ST, {llvm::Triple::Compute}); break; case attr::HLSLSV_Position: // TODO(#143523): allow use on other shader types & output once the overall // semantic logic is implemented. if (ST == llvm::Triple::Pixel) return; - DiagnoseAttrStageMismatch(AnnotationAttr, ST, {llvm::Triple::Pixel}); + DiagnoseAttrStageMismatch(SemanticAttr, ST, {llvm::Triple::Pixel}); break; default: - llvm_unreachable("Unknown HLSLAnnotationAttr"); + llvm_unreachable("Unknown SemanticAttr"); } } @@ -1661,28 +1722,30 @@ void SemaHLSL::diagnoseSystemSemanticAttr(Decl *D, const ParsedAttr &AL, diagnoseInputIDType(ValueType, AL); if (IsOutput) Diag(AL.getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL; - Attribute = createSemanticAttr<HLSLSV_DispatchThreadIDAttr>(AL, Index); + Attribute = + createSemanticAttr<HLSLSV_DispatchThreadIDAttr>(AL, nullptr, Index); } else if (SemanticName == "SV_GROUPINDEX") { if (IsOutput) Diag(AL.getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL; - Attribute = createSemanticAttr<HLSLSV_GroupIndexAttr>(AL, Index); + Attribute = createSemanticAttr<HLSLSV_GroupIndexAttr>(AL, nullptr, Index); } else if (SemanticName == "SV_GROUPTHREADID") { diagnoseInputIDType(ValueType, AL); if (IsOutput) Diag(AL.getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL; - Attribute = createSemanticAttr<HLSLSV_GroupThreadIDAttr>(AL, Index); + Attribute = + createSemanticAttr<HLSLSV_GroupThreadIDAttr>(AL, nullptr, Index); } else if (SemanticName == "SV_GROUPID") { diagnoseInputIDType(ValueType, AL); if (IsOutput) Diag(AL.getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL; - Attribute = createSemanticAttr<HLSLSV_GroupIDAttr>(AL, Index); + Attribute = createSemanticAttr<HLSLSV_GroupIDAttr>(AL, nullptr, Index); } else if (SemanticName == "SV_POSITION") { const auto *VT = ValueType->getAs<VectorType>(); if (!ValueType->hasFloatingRepresentation() || (VT && VT->getNumElements() > 4)) Diag(AL.getLoc(), diag::err_hlsl_attr_invalid_type) << AL << "float/float1/float2/float3/float4"; - Attribute = createSemanticAttr<HLSLSV_PositionAttr>(AL, Index); + Attribute = createSemanticAttr<HLSLSV_PositionAttr>(AL, nullptr, Index); } else Diag(AL.getLoc(), diag::err_hlsl_unknown_semantic) << AL; diff --git a/clang/lib/Sema/SemaOpenACC.cpp b/clang/lib/Sema/SemaOpenACC.cpp index ee9b2b3..f0f3832 100644 --- a/clang/lib/Sema/SemaOpenACC.cpp +++ b/clang/lib/Sema/SemaOpenACC.cpp @@ -3086,6 +3086,7 @@ bool SemaOpenACC::CreateReductionCombinerRecipe( case OpenACCReductionOperator::Invalid: llvm_unreachable("Invalid should have been caught above"); } + llvm_unreachable("Unhandled case"); }; auto tryCombiner = [&, this](DeclRefExpr *LHSDRE, DeclRefExpr *RHSDRE, diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 5b5b1b6..6d5cb0f 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -7246,7 +7246,9 @@ void SemaOpenMP::ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope( FunctionDecl *UDecl = nullptr; if (IsTemplated && isa<FunctionTemplateDecl>(CandidateDecl)) { auto *FTD = cast<FunctionTemplateDecl>(CandidateDecl); - if (FTD->getTemplateParameters()->size() == TemplateParamLists.size()) + // FIXME: Should this compare the template parameter lists on all levels? + if (SemaRef.Context.isSameTemplateParameterList( + FTD->getTemplateParameters(), TemplateParamLists.back())) UDecl = FTD->getTemplatedDecl(); } else if (!IsTemplated) UDecl = dyn_cast<FunctionDecl>(CandidateDecl); diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.cpp index 05d5669..42f52d0 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.cpp @@ -524,13 +524,12 @@ bool initializeScanCompilerInstance( // Use the dependency scanning optimized file system if requested to do so. if (DepFS) { DepFS->resetBypassedPathPrefix(); - if (!ScanInstance.getHeaderSearchOpts().ModuleCachePath.empty()) { - SmallString<256> ModulesCachePath; - normalizeModuleCachePath( - ScanInstance.getFileManager(), - ScanInstance.getHeaderSearchOpts().ModuleCachePath, ModulesCachePath); + SmallString<256> ModulesCachePath; + normalizeModuleCachePath(ScanInstance.getFileManager(), + ScanInstance.getHeaderSearchOpts().ModuleCachePath, + ModulesCachePath); + if (!ModulesCachePath.empty()) DepFS->setBypassedPathPrefix(ModulesCachePath); - } ScanInstance.setDependencyDirectivesGetter( std::make_unique<ScanningDependencyDirectivesGetter>( diff --git a/clang/test/AST/ByteCode/records.cpp b/clang/test/AST/ByteCode/records.cpp index 48cf811..00218ba 100644 --- a/clang/test/AST/ByteCode/records.cpp +++ b/clang/test/AST/ByteCode/records.cpp @@ -1162,6 +1162,19 @@ namespace IndirectFieldInit { static_assert(s2.x == 1 && s2.y == 2 && s2.a == 3 && s2.b == 4); #endif + + + struct B { + struct { + union { + int x = 3; + }; + int y = this->x; + }; + + constexpr B() {} + }; + static_assert(B().y == 3, ""); } namespace InheritedConstructor { @@ -1840,3 +1853,11 @@ namespace DiamondDowncast { constexpr Middle2 &fail = (Middle2&)top1; // both-error {{must be initialized by a constant expression}} \ // both-note {{cannot cast object of dynamic type 'const Bottom' to type 'Middle2'}} } + +namespace PrimitiveInitializedByInitList { + constexpr struct { + int a; + int b{this->a}; + } c{ 17 }; + static_assert(c.b == 17, ""); +} diff --git a/clang/test/CIR/CodeGen/builtin_prefetech.c b/clang/test/CIR/CodeGen/builtin_prefetech.c new file mode 100644 index 0000000..cfe85b9 --- /dev/null +++ b/clang/test/CIR/CodeGen/builtin_prefetech.c @@ -0,0 +1,43 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-cir %s -o - | FileCheck %s -check-prefix=CIR +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o - | FileCheck %s -check-prefix=LLVM +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck %s -check-prefix=OGCG + +void foo(void *a) { + __builtin_prefetch(a); // rw=0, locality=3 + __builtin_prefetch(a, 0); // rw=0, locality=3 + __builtin_prefetch(a, 1); // rw=1, locality=3 + __builtin_prefetch(a, 1, 1); // rw=1, locality=1 +} + +// CIR-LABEL: cir.func dso_local @foo( +// CIR: %[[ALLOCA:.*]] = cir.alloca !cir.ptr<!void> +// CIR: cir.store %arg0, %[[ALLOCA]] : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>> +// CIR: %[[P1:.*]] = cir.load{{.*}} %[[ALLOCA]] : !cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void> +// CIR: cir.prefetch read locality(3) %[[P1]] : !cir.ptr<!void> +// CIR: %[[P2:.*]] = cir.load{{.*}} %[[ALLOCA]] : !cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void> +// CIR: cir.prefetch read locality(3) %[[P2]] : !cir.ptr<!void> +// CIR: %[[P3:.*]] = cir.load{{.*}} %[[ALLOCA]] : !cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void> +// CIR: cir.prefetch write locality(3) %[[P3]] : !cir.ptr<!void> +// CIR: %[[P4:.*]] = cir.load{{.*}} %[[ALLOCA]] : !cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void> +// CIR: cir.prefetch write locality(1) %[[P4]] : !cir.ptr<!void> +// CIR: cir.return + +// LLVM-LABEL: define dso_local void @foo( +// LLVM: [[ALLOCA:%.*]] = alloca ptr, i64 1 +// LLVM: store ptr {{.*}}, ptr [[ALLOCA]] +// LLVM: [[LP1:%.*]] = load ptr, ptr [[ALLOCA]] +// LLVM: call void @llvm.prefetch.p0(ptr [[LP1]], i32 0, i32 3, i32 1) +// LLVM: [[LP2:%.*]] = load ptr, ptr [[ALLOCA]] +// LLVM: call void @llvm.prefetch.p0(ptr [[LP2]], i32 0, i32 3, i32 1) +// LLVM: [[LP3:%.*]] = load ptr, ptr [[ALLOCA]] +// LLVM: call void @llvm.prefetch.p0(ptr [[LP3]], i32 1, i32 3, i32 1) +// LLVM: [[LP4:%.*]] = load ptr, ptr [[ALLOCA]] +// LLVM: call void @llvm.prefetch.p0(ptr [[LP4]], i32 1, i32 1, i32 1) +// LLVM: ret void + +// OGCG-LABEL: define dso_local void @foo(ptr +// OGCG: call void @llvm.prefetch.p0(ptr {{.*}}, i32 0, i32 3, i32 1) +// OGCG: call void @llvm.prefetch.p0(ptr {{.*}}, i32 0, i32 3, i32 1) +// OGCG: call void @llvm.prefetch.p0(ptr {{.*}}, i32 1, i32 3, i32 1) +// OGCG: call void @llvm.prefetch.p0(ptr {{.*}}, i32 1, i32 1, i32 1) +// OGCG: ret void diff --git a/clang/test/CIR/CodeGen/dynamic-cast-exact.cpp b/clang/test/CIR/CodeGen/dynamic-cast-exact.cpp index e3b8533..9ddb68f 100644 --- a/clang/test/CIR/CodeGen/dynamic-cast-exact.cpp +++ b/clang/test/CIR/CodeGen/dynamic-cast-exact.cpp @@ -172,3 +172,37 @@ B *offset_cast(A *a) { // OGCG-NEXT: br label %[[LABEL_END]] // OGCG: [[LABEL_END]]: // OGCG-NEXT: phi ptr [ %[[RESULT]], %[[LABEL_NOTNULL]] ], [ null, %[[LABEL_NULL]] ] + +Derived *ptr_cast_always_fail(Base2 *ptr) { + return dynamic_cast<Derived *>(ptr); + } + +// CIR: cir.func {{.*}} @_Z20ptr_cast_always_failP5Base2 +// CIR: %{{.+}} = cir.load{{.*}} %{{.+}} : !cir.ptr<!cir.ptr<!rec_Base2>>, !cir.ptr<!rec_Base2> +// CIR-NEXT: %[[RESULT:.*]] = cir.const #cir.ptr<null> : !cir.ptr<!rec_Derived> +// CIR-NEXT: cir.store %[[RESULT]], %{{.*}} : !cir.ptr<!rec_Derived>, !cir.ptr<!cir.ptr<!rec_Derived>> + +// LLVM: define {{.*}} ptr @_Z20ptr_cast_always_failP5Base2 +// LLVM-NEXT: ret ptr null + +// OGCG: define {{.*}} ptr @_Z20ptr_cast_always_failP5Base2 +// OGCG-NEXT: entry: +// OGCG-NEXT: ret ptr null + +Derived &ref_cast_always_fail(Base2 &ref) { + return dynamic_cast<Derived &>(ref); +} + +// CIR: cir.func {{.*}} @_Z20ref_cast_always_failR5Base2 +// CIR: %{{.+}} = cir.load{{.*}} %{{.+}} : !cir.ptr<!cir.ptr<!rec_Base2>>, !cir.ptr<!rec_Base2> +// CIR-NEXT: cir.call @__cxa_bad_cast() : () -> () +// CIR-NEXT: cir.unreachable + +// LLVM: define {{.*}} ptr @_Z20ref_cast_always_failR5Base2 +// LLVM-NEXT: tail call void @__cxa_bad_cast() +// LLVM-NEXT: unreachable + +// OGCG: define {{.*}} ptr @_Z20ref_cast_always_failR5Base2 +// OGCG-NEXT: entry: +// OGCG-NEXT: tail call void @__cxa_bad_cast() +// OGCG-NEXT: unreachable diff --git a/clang/test/CIR/CodeGen/try-catch.cpp b/clang/test/CIR/CodeGen/try-catch.cpp index 5a50310..1e4d2a6 100644 --- a/clang/test/CIR/CodeGen/try-catch.cpp +++ b/clang/test/CIR/CodeGen/try-catch.cpp @@ -117,3 +117,50 @@ void try_catch_with_empty_catch_all_2() { // OGCG: %[[RESULT:.*]] = add nsw i32 %[[TMP_A]], 1 // OGCG: store i32 %[[RESULT]], ptr %[[A_ADDR]], align 4 // OGCG: ret void + +void try_catch_with_alloca() { + try { + int a; + int b; + int c = a + b; + } catch (...) { + } +} + +// CIR: cir.scope { +// CIR: %[[A_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["a"] +// CIR: %[[B_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["b"] +// CIR: %[[C_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["c", init] +// CIR: cir.try { +// CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr<!s32i>, !s32i +// CIR: %[[TMP_B:.*]] = cir.load{{.*}} %[[B_ADDR]] : !cir.ptr<!s32i>, !s32i +// CIR: %[[RESULT:.*]] = cir.binop(add, %[[TMP_A]], %[[TMP_B]]) nsw : !s32i +// CIR: cir.store{{.*}} %[[RESULT]], %[[C_ADDR]] : !s32i, !cir.ptr<!s32i> +// CIR: cir.yield +// CIR: } +// CIR: } + +// LLVM: %[[A_ADDR:.*]] = alloca i32, i64 1, align 4 +// LLVM: %[[B_ADDR:.*]] = alloca i32, i64 1, align 4 +// LLVM: %[[C_ADDR:.*]] = alloca i32, i64 1, align 4 +// LLVM: br label %[[LABEL_1:.*]] +// LLVM: [[LABEL_1]]: +// LLVM: br label %[[LABEL_2:.*]] +// LLVM: [[LABEL_2]]: +// LLVM: %[[TMP_A:.*]] = load i32, ptr %[[A_ADDR]], align 4 +// LLVM: %[[TMP_B:.*]] = load i32, ptr %[[B_ADDR]], align 4 +// LLVM: %[[RESULT:.*]] = add nsw i32 %[[TMP_A]], %[[TMP_B]] +// LLVM: store i32 %[[RESULT]], ptr %[[C_ADDR]], align 4 +// LLVM: br label %[[LABEL_3:.*]] +// LLVM: [[LABEL_3]]: +// LLVM: br label %[[LABEL_4:.*]] +// LLVM: [[LABEL_4]]: +// LLVM: ret void + +// OGCG: %[[A_ADDR:.*]] = alloca i32, align 4 +// OGCG: %[[B_ADDR:.*]] = alloca i32, align 4 +// OGCG: %[[C_ADDR:.*]] = alloca i32, align 4 +// OGCG: %[[TMP_A:.*]] = load i32, ptr %[[A_ADDR]], align 4 +// OGCG: %[[TMP_B:.*]] = load i32, ptr %[[B_ADDR]], align 4 +// OGCG: %[[RESULT:.*]] = add nsw i32 %[[TMP_A]], %[[TMP_B]] +// OGCG: store i32 %[[RESULT]], ptr %[[C_ADDR]], align 4 diff --git a/clang/test/CIR/CodeGenOpenACC/atomic-write.cpp b/clang/test/CIR/CodeGenOpenACC/atomic-write.cpp new file mode 100644 index 0000000..1685534 --- /dev/null +++ b/clang/test/CIR/CodeGenOpenACC/atomic-write.cpp @@ -0,0 +1,55 @@ +// RUN: %clang_cc1 -fopenacc -triple x86_64-linux-gnu -Wno-openacc-self-if-potential-conflict -emit-cir -fclangir -triple x86_64-linux-pc %s -o - | FileCheck %s + +extern "C" bool condition(int x, unsigned int y, float f); +extern "C" double do_thing(float f); + +struct ConvertsToScalar { + operator float(); +}; + +void use(int x, unsigned int y, float f, ConvertsToScalar cts) { + // CHECK: cir.func{{.*}}(%[[X_ARG:.*]]: !s32i{{.*}}, %[[Y_ARG:.*]]: !u32i{{.*}}, %[[F_ARG:.*]]: !cir.float{{.*}}){{.*}}, %[[CTS_ARG:.*]]: !rec_ConvertsToScalar{{.*}}) { + // CHECK-NEXT: %[[X_ALLOC:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["x", init] + // CHECK-NEXT: %[[Y_ALLOC:.*]] = cir.alloca !u32i, !cir.ptr<!u32i>, ["y", init] + // CHECK-NEXT: %[[F_ALLOC:.*]] = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["f", init] + // CHECK-NEXT: %[[CTS_ALLOC:.*]] = cir.alloca !rec_ConvertsToScalar, !cir.ptr<!rec_ConvertsToScalar>, ["cts", init] + // + // CHECK-NEXT: cir.store %[[X_ARG]], %[[X_ALLOC]] : !s32i, !cir.ptr<!s32i> + // CHECK-NEXT: cir.store %[[Y_ARG]], %[[Y_ALLOC]] : !u32i, !cir.ptr<!u32i> + // CHECK-NEXT: cir.store %[[F_ARG]], %[[F_ALLOC]] : !cir.float, !cir.ptr<!cir.float> + // CHECK-NEXT: cir.store %[[CTS_ARG]], %[[CTS_ALLOC]] : !rec_ConvertsToScalar, !cir.ptr<!rec_ConvertsToScalar> + + // CHECK-NEXT: %[[Y_LOAD:.*]] = cir.load {{.*}}%[[Y_ALLOC]] : !cir.ptr<!u32i>, !u32i + // CHECK-NEXT: %[[Y_TO_FLOAT:.*]] = cir.cast int_to_float %[[Y_LOAD]] : !u32i -> !cir.float + // CHECK-NEXT: %[[F_LOAD:.*]] = cir.load {{.*}}%[[F_ALLOC]] : !cir.ptr<!cir.float>, !cir.float + // CHECK-NEXT: %[[MUL:.*]] = cir.binop(mul, %[[Y_TO_FLOAT]], %[[F_LOAD]]) : !cir.float + // CHECK-NEXT: %[[RHS_CAST:.*]] = cir.cast float_to_int %[[MUL]] : !cir.float -> !s32i + // CHECK-NEXT: acc.atomic.write %[[X_ALLOC]] = %[[RHS_CAST]] : !cir.ptr<!s32i>, !s32i +#pragma acc atomic write + x = y * f; + + // CHECK-NEXT: %[[F_LOAD:.*]] = cir.load {{.*}}%[[F_ALLOC]] : !cir.ptr<!cir.float>, !cir.float + // CHECK-NEXT: %[[CALL:.*]] = cir.call @do_thing(%[[F_LOAD]]) : (!cir.float) -> !cir.double + // CHECK-NEXT: %[[CALL_CAST:.*]] = cir.cast float_to_int %[[CALL]] : !cir.double -> !u32i + // CHECK-NEXT: acc.atomic.write %[[Y_ALLOC]] = %[[CALL_CAST]] : !cir.ptr<!u32i>, !u32i +#pragma acc atomic write + y = do_thing(f); + + // CHECK-NEXT: %[[X_LOAD:.*]] = cir.load {{.*}}%[[X_ALLOC]] : !cir.ptr<!s32i>, !s32i + // CHECK-NEXT: %[[X_CAST:.*]] = cir.cast int_to_float %[[X_LOAD]] : !s32i -> !cir.float + // CHECK-NEXT: %[[THING_CALL:.*]] = cir.call @do_thing(%[[X_CAST]]) : (!cir.float) -> !cir.double + // CHECK-NEXT: %[[THING_CAST:.*]] = cir.cast floating %[[THING_CALL]] : !cir.double -> !cir.float + // CHECK-NEXT: %[[X_LOAD:.*]] = cir.load {{.*}}%[[X_ALLOC]] : !cir.ptr<!s32i>, !s32i + // CHECK-NEXT: %[[Y_LOAD:.*]] = cir.load {{.*}}%[[Y_ALLOC]] : !cir.ptr<!u32i>, !u32i + // CHECK-NEXT: %[[F_LOAD:.*]] = cir.load {{.*}}%[[F_ALLOC]] : !cir.ptr<!cir.float>, !cir.float + // CHECK-NEXT: %[[COND_CALL:.*]] = cir.call @condition(%[[X_LOAD]], %[[Y_LOAD]], %[[F_LOAD]]) : (!s32i, !u32i, !cir.float) -> !cir.bool + // CHECK-NEXT: %[[COND_CAST:.*]] = builtin.unrealized_conversion_cast %[[COND_CALL]] : !cir.bool to i1 + // CHECK-NEXT: acc.atomic.write if(%[[COND_CAST]]) %[[F_ALLOC]] = %[[THING_CAST]] : !cir.ptr<!cir.float>, !cir.float +#pragma acc atomic write if (condition(x, y, f)) + f = do_thing(x); + + // CHECK-NEXT: %[[CTS_CONV_CALL:.*]] = cir.call @{{.*}}(%[[CTS_ALLOC]]) : (!cir.ptr<!rec_ConvertsToScalar>) -> !cir.float + // CHECK-NEXT: acc.atomic.write %[[F_ALLOC]] = %[[CTS_CONV_CALL]] : !cir.ptr<!cir.float>, !cir.float +#pragma acc atomic write + f = cts; +} diff --git a/clang/test/CodeGen/X86/avx2-builtins.c b/clang/test/CodeGen/X86/avx2-builtins.c index 03b1bde..5c52d84 100644 --- a/clang/test/CodeGen/X86/avx2-builtins.c +++ b/clang/test/CodeGen/X86/avx2-builtins.c @@ -1155,23 +1155,30 @@ __m256i test_mm256_shufflelo_epi16(__m256i a) { return _mm256_shufflelo_epi16(a, 83); } TEST_CONSTEXPR(match_v16hi(_mm256_shufflelo_epi16(((__m256i)(__v16hi){ 0,1,2,3, 4,5,6,7, 8,9,10,11, 12,13,14,15}), 83), 3,0,1,1, 4,5,6,7, 11,8,9,9, 12,13,14,15) ); + __m256i test_mm256_sign_epi8(__m256i a, __m256i b) { // CHECK-LABEL: test_mm256_sign_epi8 // CHECK: call <32 x i8> @llvm.x86.avx2.psign.b(<32 x i8> %{{.*}}, <32 x i8> %{{.*}}) return _mm256_sign_epi8(a, b); } +TEST_CONSTEXPR(match_v32qi(_mm256_sign_epi8( + (__m256i)(__v32qs){0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, + (__m256i)(__v32qs){0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1}), + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1)); __m256i test_mm256_sign_epi16(__m256i a, __m256i b) { // CHECK-LABEL: test_mm256_sign_epi16 // CHECK: call <16 x i16> @llvm.x86.avx2.psign.w(<16 x i16> %{{.*}}, <16 x i16> %{{.*}}) return _mm256_sign_epi16(a, b); } +TEST_CONSTEXPR(match_v16hi(_mm256_sign_epi16((__m256i)(__v16hi){0x77,0x77,0xbe,0xbe, -0x9,-0x9,-0x8,-0x8, 0,0,0,0, 0,0,0,0}, (__m256i)(__v16hi){-1,-256,1,256, -512,-1028,512,1028, -2048,-4096,0,0, 0,0,0,0}), -0x77,-0x77,0xbe,0xbe, 0x9,0x9,-0x8,-0x8, 0,0,0,0, 0,0,0,0)); __m256i test_mm256_sign_epi32(__m256i a, __m256i b) { // CHECK-LABEL: test_mm256_sign_epi32 // CHECK: call <8 x i32> @llvm.x86.avx2.psign.d(<8 x i32> %{{.*}}, <8 x i32> %{{.*}}) return _mm256_sign_epi32(a, b); } +TEST_CONSTEXPR(match_v8si(_mm256_sign_epi32((__m256i)(__v8si){0xbeef,0xfeed,0xbead,0xdeed, -1,2,-3,4}, (__m256i)(__v8si){0,0,0,0,-1,-1,-1,-1}), 0,0,0,0, 1,-2,3,-4)); __m256i test_mm256_slli_epi16(__m256i a) { // CHECK-LABEL: test_mm256_slli_epi16 diff --git a/clang/test/CodeGen/X86/mmx-builtins.c b/clang/test/CodeGen/X86/mmx-builtins.c index 7674255..2731380 100644 --- a/clang/test/CodeGen/X86/mmx-builtins.c +++ b/clang/test/CodeGen/X86/mmx-builtins.c @@ -602,23 +602,28 @@ __m64 test_mm_shuffle_pi16(__m64 a) { return _mm_shuffle_pi16(a, 3); } TEST_CONSTEXPR(match_v4hi(_mm_shuffle_pi16(((__m64)(__v4hi){0,1,2,3}), 3), 3,0,0,0)); + __m64 test_mm_sign_pi8(__m64 a, __m64 b) { // CHECK-LABEL: test_mm_sign_pi8 // CHECK: call <16 x i8> @llvm.x86.ssse3.psign.b.128( return _mm_sign_pi8(a, b); } +TEST_CONSTEXPR(match_v8qi(_mm_sign_pi8((__m64)(__v8qi){0,0,0,0, 0,0,0,0}, (__m64)(__v8qi){0,0,0,0, 0,0,0,0}), 0,0,0,0, 0,0,0,0)); +TEST_CONSTEXPR(match_v8qi(_mm_sign_pi8((__m64)(__v8qi){6,7,6,7, 6,7,6,7}, (__m64)(__v8qi){1,1,1,1, 0,0,0,0}), 6,7,6,7, 0,0,0,0)); __m64 test_mm_sign_pi16(__m64 a, __m64 b) { // CHECK-LABEL: test_mm_sign_pi16 // CHECK: call <8 x i16> @llvm.x86.ssse3.psign.w.128( return _mm_sign_pi16(a, b); } +TEST_CONSTEXPR(match_v4hi(_mm_sign_pi16((__m64)(__v4hi){-1,0,1,0}, (__m64)(__v4hi){1,0,-1,0}), -1,0,-1,0)); __m64 test_mm_sign_pi32(__m64 a, __m64 b) { // CHECK-LABEL: test_mm_sign_pi32 // CHECK: call <4 x i32> @llvm.x86.ssse3.psign.d.128( return _mm_sign_pi32(a, b); } +TEST_CONSTEXPR(match_v2si(_mm_sign_pi32((__m64)(__v2si){0x7FFF, -1}, (__m64)(__v2si){-1, 0x7FFF}), -0x7FFF, -1)); __m64 test_mm_sll_pi16(__m64 a, __m64 b) { // CHECK-LABEL: test_mm_sll_pi16 diff --git a/clang/test/CodeGen/X86/ssse3-builtins.c b/clang/test/CodeGen/X86/ssse3-builtins.c index f70afc0..b7a4a2f 100644 --- a/clang/test/CodeGen/X86/ssse3-builtins.c +++ b/clang/test/CodeGen/X86/ssse3-builtins.c @@ -125,15 +125,18 @@ __m128i test_mm_sign_epi8(__m128i a, __m128i b) { // CHECK: call <16 x i8> @llvm.x86.ssse3.psign.b.128(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}) return _mm_sign_epi8(a, b); } +TEST_CONSTEXPR(match_v16qi(_mm_sign_epi8((__m128i)(__v16qs){11,0,13,14, 0,16,17,18, 19,20,21,22, 23,24,25,26}, (__m128i)(__v16qs){0,1,0,1, -1,1,0,0, 0,0,1,1, -1,0,-1,0}), 0,0,0,14, 0,16,0,0, 0,0,21,22, -23,0,-25,0)); __m128i test_mm_sign_epi16(__m128i a, __m128i b) { // CHECK-LABEL: test_mm_sign_epi16 // CHECK: call <8 x i16> @llvm.x86.ssse3.psign.w.128(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}) return _mm_sign_epi16(a, b); } +TEST_CONSTEXPR(match_v8hi(_mm_sign_epi16((__m128i)(__v8hi){0,-2,0,-4,0,-6,0,-8}, (__m128i)(__v8hi){-1,-2,-3,-4,-5,-6,7,-8}), 0,2,0,4,0,6,0,8)); __m128i test_mm_sign_epi32(__m128i a, __m128i b) { // CHECK-LABEL: test_mm_sign_epi32 // CHECK: call <4 x i32> @llvm.x86.ssse3.psign.d.128(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}) return _mm_sign_epi32(a, b); } +TEST_CONSTEXPR(match_v4si(_mm_sign_epi32((__m128i)(__v4si){-1,-2,-3,-4}, (__m128i)(__v4si){-4,-3,-2,-1}), 1,2,3,4)); diff --git a/clang/test/CodeGenHLSL/semantics/semantic-struct-1.hlsl b/clang/test/CodeGenHLSL/semantics/semantic-struct-1.hlsl new file mode 100644 index 0000000..ddd0bae --- /dev/null +++ b/clang/test/CodeGenHLSL/semantics/semantic-struct-1.hlsl @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-DXIL -DTARGET=dx +// RUN: %clang_cc1 -triple spirv-linux-vulkan-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV -DTARGET=spv + + +struct Input { + uint Idx : SV_DispatchThreadID; + +}; + +// Make sure SV_DispatchThreadID translated into dx.thread.id. + +// CHECK: define void @foo() +// CHECK-DXIL: %[[#ID:]] = call i32 @llvm.[[TARGET]].thread.id(i32 0) +// CHECK-SPIRV: %[[#ID:]] = call i32 @llvm.[[TARGET]].thread.id.i32(i32 0) +// CHECK: %[[#TMP:]] = insertvalue %struct.Input poison, i32 %[[#ID]], 0 +// CHECK: %[[#VAR:]] = alloca %struct.Input, align 8 +// CHECK: store %struct.Input %[[#TMP]], ptr %[[#VAR]], align 4 +// CHECK-DXIL: call void @{{.*}}foo{{.*}}(ptr %[[#VAR]]) +// CHECK-SPIRV: call spir_func void @{{.*}}foo{{.*}}(ptr %[[#VAR]]) +[shader("compute")] +[numthreads(8,8,1)] +void foo(Input input) {} + diff --git a/clang/test/CodeGenHLSL/semantics/semantic-struct-2.hlsl b/clang/test/CodeGenHLSL/semantics/semantic-struct-2.hlsl new file mode 100644 index 0000000..0d9c91e --- /dev/null +++ b/clang/test/CodeGenHLSL/semantics/semantic-struct-2.hlsl @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-DXIL -DTARGET=dx +// RUN: %clang_cc1 -triple spirv-linux-vulkan-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV -DTARGET=spv + + +struct Input { + uint Idx : SV_DispatchThreadID; + uint Gid : SV_GroupID; +}; + +// Make sure SV_DispatchThreadID translated into dx.thread.id. + +// CHECK: define void @foo() +// CHECK-DXIL: %[[#ID:]] = call i32 @llvm.[[TARGET]].thread.id(i32 0) +// CHECK-SPIRV: %[[#ID:]] = call i32 @llvm.[[TARGET]].thread.id.i32(i32 0) +// CHECK: %[[#TMP1:]] = insertvalue %struct.Input poison, i32 %[[#ID]], 0 +// CHECK-DXIL: %[[#GID:]] = call i32 @llvm.[[TARGET]].group.id(i32 0) +// CHECK-SPIRV:%[[#GID:]] = call i32 @llvm.[[TARGET]].group.id.i32(i32 0) +// CHECK: %[[#TMP2:]] = insertvalue %struct.Input %[[#TMP1]], i32 %[[#GID]], 1 +// CHECK: %[[#VAR:]] = alloca %struct.Input, align 8 +// CHECK: store %struct.Input %[[#TMP2]], ptr %[[#VAR]], align 4 +// CHECK-DXIL: call void @{{.*}}foo{{.*}}(ptr %[[#VAR]]) +// CHECK-SPIRV: call spir_func void @{{.*}}foo{{.*}}(ptr %[[#VAR]]) +[shader("compute")] +[numthreads(8,8,1)] +void foo(Input input) {} diff --git a/clang/test/CodeGenHLSL/semantics/semantic-struct-nested-inherit.hlsl b/clang/test/CodeGenHLSL/semantics/semantic-struct-nested-inherit.hlsl new file mode 100644 index 0000000..f4c4d86 --- /dev/null +++ b/clang/test/CodeGenHLSL/semantics/semantic-struct-nested-inherit.hlsl @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-DXIL -DTARGET=dx +// RUN: %clang_cc1 -triple spirv-linux-vulkan-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV -DTARGET=spv + + +struct Inner { + uint Gid; +}; + +struct Input { + uint Idx : SV_DispatchThreadID; + Inner inner : SV_GroupIndex; +}; + +// Make sure SV_DispatchThreadID translated into dx.thread.id. + +// CHECK: define void @foo() +// CHECK-DXIL: %[[#ID:]] = call i32 @llvm.[[TARGET]].thread.id(i32 0) +// CHECK-SPIRV: %[[#ID:]] = call i32 @llvm.[[TARGET]].thread.id.i32(i32 0) +// CHECK: %[[#TMP1:]] = insertvalue %struct.Input poison, i32 %[[#ID]], 0 +// CHECK-DXIL: %[[#GID:]] = call i32 @llvm.dx.flattened.thread.id.in.group() +// CHECK-SPIRV:%[[#GID:]] = call i32 @llvm.spv.flattened.thread.id.in.group() +// CHECK: %[[#TMP2:]] = insertvalue %struct.Inner poison, i32 %[[#GID]], 0 +// CHECK: %[[#TMP3:]] = insertvalue %struct.Input %[[#TMP1]], %struct.Inner %[[#TMP2]], 1 +// CHECK: %[[#VAR:]] = alloca %struct.Input, align 8 +// CHECK: store %struct.Input %[[#TMP3]], ptr %[[#VAR]], align 4 +// CHECK-DXIL: call void @{{.*}}foo{{.*}}(ptr %[[#VAR]]) +// CHECK-SPIRV: call spir_func void @{{.*}}foo{{.*}}(ptr %[[#VAR]]) +[shader("compute")] +[numthreads(8,8,1)] +void foo(Input input) {} diff --git a/clang/test/CodeGenHLSL/semantics/semantic-struct-nested-shadow.hlsl b/clang/test/CodeGenHLSL/semantics/semantic-struct-nested-shadow.hlsl new file mode 100644 index 0000000..e1344dd --- /dev/null +++ b/clang/test/CodeGenHLSL/semantics/semantic-struct-nested-shadow.hlsl @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-DXIL -DTARGET=dx +// RUN: %clang_cc1 -triple spirv-linux-vulkan-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV -DTARGET=spv + + +struct Inner { + uint Gid : SV_GroupID; +}; + +struct Input { + uint Idx : SV_DispatchThreadID; + Inner inner : SV_GroupIndex; +}; + +// Make sure SV_DispatchThreadID translated into dx.thread.id. + +// CHECK: define void @foo() +// CHECK-DXIL: %[[#ID:]] = call i32 @llvm.[[TARGET]].thread.id(i32 0) +// CHECK-SPIRV: %[[#ID:]] = call i32 @llvm.[[TARGET]].thread.id.i32(i32 0) +// CHECK: %[[#TMP1:]] = insertvalue %struct.Input poison, i32 %[[#ID]], 0 +// CHECK-DXIL: %[[#GID:]] = call i32 @llvm.dx.flattened.thread.id.in.group() +// CHECK-SPIRV:%[[#GID:]] = call i32 @llvm.spv.flattened.thread.id.in.group() +// CHECK: %[[#TMP2:]] = insertvalue %struct.Inner poison, i32 %[[#GID]], 0 +// CHECK: %[[#TMP3:]] = insertvalue %struct.Input %[[#TMP1]], %struct.Inner %[[#TMP2]], 1 +// CHECK: %[[#VAR:]] = alloca %struct.Input, align 8 +// CHECK: store %struct.Input %[[#TMP3]], ptr %[[#VAR]], align 4 +// CHECK-DXIL: call void @{{.*}}foo{{.*}}(ptr %[[#VAR]]) +// CHECK-SPIRV: call spir_func void @{{.*}}foo{{.*}}(ptr %[[#VAR]]) +[shader("compute")] +[numthreads(8,8,1)] +void foo(Input input) {} diff --git a/clang/test/CodeGenHLSL/semantics/semantic-struct-nested.hlsl b/clang/test/CodeGenHLSL/semantics/semantic-struct-nested.hlsl new file mode 100644 index 0000000..cd6f946 --- /dev/null +++ b/clang/test/CodeGenHLSL/semantics/semantic-struct-nested.hlsl @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-DXIL -DTARGET=dx +// RUN: %clang_cc1 -triple spirv-linux-vulkan-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV -DTARGET=spv + + +struct Inner { + uint Gid : SV_GroupID; +}; + +struct Input { + uint Idx : SV_DispatchThreadID; + Inner inner; +}; + +// Make sure SV_DispatchThreadID translated into dx.thread.id. + +// CHECK: define void @foo() +// CHECK-DXIL: %[[#ID:]] = call i32 @llvm.[[TARGET]].thread.id(i32 0) +// CHECK-SPIRV: %[[#ID:]] = call i32 @llvm.[[TARGET]].thread.id.i32(i32 0) +// CHECK: %[[#TMP1:]] = insertvalue %struct.Input poison, i32 %[[#ID]], 0 +// CHECK-DXIL: %[[#GID:]] = call i32 @llvm.[[TARGET]].group.id(i32 0) +// CHECK-SPIRV:%[[#GID:]] = call i32 @llvm.[[TARGET]].group.id.i32(i32 0) +// CHECK: %[[#TMP2:]] = insertvalue %struct.Inner poison, i32 %[[#GID]], 0 +// CHECK: %[[#TMP3:]] = insertvalue %struct.Input %[[#TMP1]], %struct.Inner %[[#TMP2]], 1 +// CHECK: %[[#VAR:]] = alloca %struct.Input, align 8 +// CHECK: store %struct.Input %[[#TMP3]], ptr %[[#VAR]], align 4 +// CHECK-DXIL: call void @{{.*}}foo{{.*}}(ptr %[[#VAR]]) +// CHECK-SPIRV: call spir_func void @{{.*}}foo{{.*}}(ptr %[[#VAR]]) +[shader("compute")] +[numthreads(8,8,1)] +void foo(Input input) {} diff --git a/clang/test/Driver/DTLTO/Inputs/dtlto-helper.py b/clang/test/Driver/DTLTO/Inputs/dtlto-helper.py new file mode 100644 index 0000000..6eb9f68 --- /dev/null +++ b/clang/test/Driver/DTLTO/Inputs/dtlto-helper.py @@ -0,0 +1,11 @@ +from pathlib import Path +import sys + +# Arg 1: "clang" path. +p = Path(sys.argv[1]) +print(f"clang-name:{p.resolve().name}") +# Arg 2: Non-zero for LLVM driver. +if sys.argv[2] != "0": + print(f'prepend-arg:"--thinlto-remote-compiler-prepend-arg={p.name}"') +else: + print("prepend-arg: ") diff --git a/clang/test/Driver/DTLTO/dtlto.c b/clang/test/Driver/DTLTO/dtlto.c index f31b635..5fbf788 100644 --- a/clang/test/Driver/DTLTO/dtlto.c +++ b/clang/test/Driver/DTLTO/dtlto.c @@ -3,16 +3,18 @@ /// Check DTLTO options are forwarded to the linker. /// Check that options are forwarded as expected with --thinlto-distributor=. -// RUN: %python %S/filename.py %clang > %t_forward.log +// RUN: %python %S/Inputs/dtlto-helper.py %clang %llvm-driver > %t_forward.log // RUN: %clang -flto=thin %s -### -fuse-ld=lld --target=x86_64-linux-gnu \ // RUN: -Xthinlto-distributor=a1 -Xthinlto-distributor=a2,a3 \ // RUN: -fthinlto-distributor=d.exe -Werror >>%t_forward.log 2>&1 // RUN: FileCheck %s --input-file=%t_forward.log --check-prefix=FORWARD -// FORWARD: filename.py:[[CLANG:.*]] -// FORWARD: ld.lld +// FORWARD: clang-name:[[CLANG:.*]] +// FORWARD-NEXT: prepend-arg:[[PREPEND_ARG:.*]] +// FORWARD: ld.lld // FORWARD-SAME: "--thinlto-distributor=d.exe" // FORWARD-SAME: "--thinlto-remote-compiler={{[^"]*}}[[CLANG]]" +// FORWARD-SAME: [[PREPEND_ARG]] // FORWARD-SAME: "--thinlto-distributor-arg=a1" // FORWARD-SAME: "--thinlto-distributor-arg=a2" // FORWARD-SAME: "--thinlto-distributor-arg=a3" @@ -30,24 +32,25 @@ /// Check the expected arguments are forwarded by default with only /// --thinlto-distributor=. -// RUN: %python %S/filename.py %clang > %t_default.log +// RUN: %python %S/Inputs/dtlto-helper.py %clang %llvm-driver > %t_default.log // RUN: %clang -flto=thin %s -### -fuse-ld=lld --target=x86_64-linux-gnu \ // RUN: -fthinlto-distributor=d.exe -Werror >>%t_default.log 2>&1 // RUN: FileCheck %s --input-file=%t_default.log --check-prefix=DEFAULT \ // RUN: --implicit-check-not=distributor --implicit-check-not=remote-compiler -// DEFAULT: filename.py:[[CLANG:.*]] -// DEFAULT: ld.lld +// DEFAULT: clang-name:[[CLANG:.*]] +// DEFAULT-NEXT: prepend-arg:[[PREPEND_ARG:.*]] +// DEFAULT: ld.lld // DEFAULT-SAME: "--thinlto-distributor=d.exe" // DEFAULT-SAME: "--thinlto-remote-compiler={{[^"]*}}[[CLANG]]" +// DEFAULT-SAME: [[PREPEND_ARG]] /// Check that nothing is forwarded when the compiler is not in LTO mode, and that /// appropriate unused option warnings are issued. -// RUN: %python %S/filename.py %clang > %t_noflto.log // RUN: %clang %s -### -fuse-ld=lld --target=x86_64-linux-gnu \ -// RUN: -fthinlto-distributor=d.exe >>%t_noflto.log 2>&1 -// RUN: FileCheck %s --input-file=%t_noflto.log --check-prefix=NOFLTO \ -// RUN: --implicit-check-not=distributor --implicit-check-not=remote-compiler +// RUN: -fthinlto-distributor=d.exe 2>&1 | \ +// RUN: FileCheck %s --check-prefix=NOFLTO --implicit-check-not=distributor \ +// RUN: --implicit-check-not=remote-compiler // NOFLTO: warning: argument unused during compilation: '-fthinlto-distributor=d.exe' // NOFLTO: ld.lld diff --git a/clang/test/Driver/DTLTO/filename.py b/clang/test/Driver/DTLTO/filename.py deleted file mode 100644 index df1aeb6..0000000 --- a/clang/test/Driver/DTLTO/filename.py +++ /dev/null @@ -1,4 +0,0 @@ -from pathlib import Path -import sys - -print(f"filename.py:{Path(sys.argv[1]).resolve().name}") diff --git a/clang/test/Driver/DTLTO/lit.local.cfg b/clang/test/Driver/DTLTO/lit.local.cfg new file mode 100644 index 0000000..0756c5c --- /dev/null +++ b/clang/test/Driver/DTLTO/lit.local.cfg @@ -0,0 +1,3 @@ +from lit.llvm import llvm_config + +config.substitutions.append(("%llvm-driver", "1" if "llvm-driver" in config.available_features else "0")) diff --git a/clang/test/Driver/DTLTO/ps5-dtlto.c b/clang/test/Driver/DTLTO/ps5-dtlto.c index 4c10a02..b59fb48 100644 --- a/clang/test/Driver/DTLTO/ps5-dtlto.c +++ b/clang/test/Driver/DTLTO/ps5-dtlto.c @@ -3,16 +3,18 @@ /// Check DTLTO options are forwarded to the linker. /// Check that options are forwarded as expected with --thinlto-distributor=. -// RUN: %python %S/filename.py %clang > %t_forward.log +// RUN: %python %S/Inputs/dtlto-helper.py %clang %llvm-driver > %t_forward.log // RUN: %clang -flto=thin %s -### --target=x86_64-sie-ps5 \ // RUN: -Xthinlto-distributor=a1 -Xthinlto-distributor=a2,a3 \ // RUN: -fthinlto-distributor=d.exe -Werror >>%t_forward.log 2>&1 // RUN: FileCheck %s --input-file=%t_forward.log --check-prefix=FORWARD -// FORWARD: filename.py:[[CLANG:.*]] -// FORWARD: prospero-lld +// FORWARD: clang-name:[[CLANG:.*]] +// FORWARD-NEXT: prepend-arg:[[PREPEND_ARG:.*]] +// FORWARD: prospero-lld // FORWARD-SAME: "--thinlto-distributor=d.exe" // FORWARD-SAME: "--thinlto-remote-compiler={{[^"]*}}[[CLANG]]" +// FORWARD-SAME: [[PREPEND_ARG]] // FORWARD-SAME: "--thinlto-distributor-arg=a1" // FORWARD-SAME: "--thinlto-distributor-arg=a2" // FORWARD-SAME: "--thinlto-distributor-arg=a3" @@ -30,20 +32,22 @@ /// Check the expected arguments are forwarded by default with only /// --thinlto-distributor=. -// RUN: %python %S/filename.py %clang > %t_default.log +// RUN: %python %S/Inputs/dtlto-helper.py %clang %llvm-driver > %t_default.log // RUN: %clang -flto=thin %s -### --target=x86_64-sie-ps5 \ // RUN: -fthinlto-distributor=d.exe -Werror >>%t_default.log 2>&1 // RUN: FileCheck %s --input-file=%t_default.log --check-prefix=DEFAULT \ // RUN: --implicit-check-not=distributor --implicit-check-not=remote-compiler -// DEFAULT: filename.py:[[CLANG:.*]] -// DEFAULT: prospero-lld +// DEFAULT: clang-name:[[CLANG:.*]] +// DEFAULT-NEXT: prepend-arg:[[PREPEND_ARG:.*]] +// DEFAULT: prospero-lld // DEFAULT-SAME: "--thinlto-distributor=d.exe" // DEFAULT-SAME: "--thinlto-remote-compiler={{[^"]*}}[[CLANG]]" +// DEFAULT-SAME: [[PREPEND_ARG]] /// Check that the arguments are forwarded unconditionally even when the /// compiler is not in LTO mode. -// RUN: %python %S/filename.py %clang > %t_noflto.log +// RUN: %python %S/Inputs/dtlto-helper.py %clang %llvm-driver > %t_noflto.log // RUN: %clang %s -### --target=x86_64-sie-ps5 \ // RUN: -fthinlto-distributor=d.exe -Werror >>%t_noflto.log 2>&1 // RUN: FileCheck %s --input-file=%t_noflto.log --check-prefix=DEFAULT \ diff --git a/clang/test/Headers/floatneeds.c b/clang/test/Headers/floatneeds.c new file mode 100644 index 0000000..e544b41 --- /dev/null +++ b/clang/test/Headers/floatneeds.c @@ -0,0 +1,41 @@ +// RUN: rm -fR %t +// RUN: split-file %s %t +// RUN: %clang_cc1 -fsyntax-only -verify=c99 -std=c99 %t/floatneeds0.c +// RUN: %clang_cc1 -fsyntax-only -verify=c99 -std=c99 %t/floatneeds1.c +// RUN: %clang_cc1 -fsyntax-only -verify=c23 -std=c23 %t/floatneeds0.c +// RUN: %clang_cc1 -fsyntax-only -verify=c23 -std=c23 %t/floatneeds1.c +// RUN: %clang_cc1 -fsyntax-only -verify=c99-modules -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -std=c99 %t/floatneeds0.c +// RUN: %clang_cc1 -fsyntax-only -verify=c99-modules -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -std=c99 %t/floatneeds1.c +// RUN: %clang_cc1 -fsyntax-only -verify=c23-modules -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -std=c23 %t/floatneeds0.c +// RUN: %clang_cc1 -fsyntax-only -verify=c23-modules -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -std=c23 %t/floatneeds1.c + +// Use C99 to verify that __need_ can be used to get types that wouldn't normally be available. + +//--- floatneeds0.c +float infinity0 = INFINITY; // c99-error{{undeclared identifier 'INFINITY'}} c23-error{{undeclared identifier 'INFINITY'}} \ + c99-modules-error{{undeclared identifier 'INFINITY'}} c23-modules-error{{undeclared identifier 'INFINITY'}} +float nan0 = NAN; // c99-error{{undeclared identifier 'NAN'}} c23-error{{undeclared identifier 'NAN'}} \ + c99-modules-error{{undeclared identifier 'NAN'}} c23-modules-error{{undeclared identifier 'NAN'}} +float max0 = FLT_MAX; // c99-error{{undeclared identifier 'FLT_MAX'}} c23-error{{undeclared identifier 'FLT_MAX'}} \ + c99-modules-error{{undeclared identifier 'FLT_MAX'}} c23-modules-error{{undeclared identifier 'FLT_MAX'}} + +#define __need_infinity_nan +#include <float.h> +float infinity1 = INFINITY; +float nan1 = NAN; +float max1 = FLT_MAX; // c99-error{{undeclared identifier}} c23-error{{undeclared identifier}} \ + c99-modules-error{{undeclared identifier}} c23-modules-error{{undeclared identifier}} + +#include <float.h> +float infinity2 = INFINITY; +float nan2 = NAN; +float max2 = FLT_MAX; + +//--- floatneeds1.c +// c23-no-diagnostics +// c23-modules-no-diagnostics + +#include <float.h> +float infinity0 = INFINITY; // c99-error{{undeclared identifier}} c99-modules-error{{undeclared identifier}} +float nan0 = NAN; // c99-error{{undeclared identifier}} c99-modules-error{{undeclared identifier}} +float max0 = FLT_MAX; diff --git a/clang/test/Modules/explicit-build-cwd.c b/clang/test/Modules/explicit-build-cwd.c new file mode 100644 index 0000000..af8b743 --- /dev/null +++ b/clang/test/Modules/explicit-build-cwd.c @@ -0,0 +1,17 @@ +// This test checks that explicitly building the same module from different +// working directories results in the same PCM contents. + +// RUN: rm -rf %t +// RUN: split-file %s %t +// RUN: mkdir %t/one +// RUN: mkdir %t/two + +//--- module.modulemap +module M { header "M.h" } + +//--- M.h + +// RUN: cd %t/one && %clang_cc1 -fmodules -emit-module %t/module.modulemap -fmodule-name=M -o %t/M_one.pcm +// RUN: cd %t/two && %clang_cc1 -fmodules -emit-module %t/module.modulemap -fmodule-name=M -o %t/M_two.pcm + +// RUN: diff %t/M_one.pcm %t/M_two.pcm diff --git a/clang/test/Modules/relative-resource-dir.m b/clang/test/Modules/relative-resource-dir.m index 96f2d8e..1183184 100644 --- a/clang/test/Modules/relative-resource-dir.m +++ b/clang/test/Modules/relative-resource-dir.m @@ -8,5 +8,6 @@ // RUN: -fimplicit-module-maps -fmodules-cache-path=%t.mcp \ // RUN: -fbuiltin-headers-in-system-modules \ // RUN: -resource-dir resource-dir \ +// RUN: -internal-isystem resource-dir/include \ // RUN: -emit-module %S/Inputs/builtin-headers/module.modulemap \ // RUN: -fmodule-name=ModuleWithBuiltinHeader -o %t.pcm diff --git a/clang/test/Preprocessor/cxx_oper_comma.cpp b/clang/test/Preprocessor/cxx_oper_comma.cpp new file mode 100644 index 0000000..5db803a --- /dev/null +++ b/clang/test/Preprocessor/cxx_oper_comma.cpp @@ -0,0 +1,45 @@ +// RUN: %clang_cc1 -E -pedantic-errors %s -verify -std=c++98 +// RUN: %clang_cc1 -E -pedantic-errors %s -verify -std=c++11 +// RUN: %clang_cc1 -E -pedantic-errors %s -verify -std=c++14 +// RUN: %clang_cc1 -E -pedantic-errors %s -verify -std=c++17 +// RUN: %clang_cc1 -E -pedantic-errors %s -verify -std=c++20 +// RUN: %clang_cc1 -E -pedantic-errors %s -verify=expected,since-cxx23 -std=c++23 -Wno-c23-extensions +// RUN: %clang_cc1 -E -pedantic-errors %s -verify=expected,since-cxx23 -std=c++2c -Wno-c23-extensions + +// Test 1: Top-level comma +// expected-error@+1 {{expected end of line in preprocessor expression}} +#if 1, 2 +#endif + +// Test 2: Comma in conditional expression(CWG3017) +// Per CWG 3017, this exact case highlights the specification gap +// where C++ lacks explicit prohibition of comma operators in #if +// expected-error@+1 {{comma operator in operand of #if}} +#if 1 ? 1, 0 : 3 +#endif + +// Test 3: Parenthesized comma +// expected-error@+1 {{comma operator in operand of #if}} +#if (1, 2) +#endif + +// Test 4: Multiple commas +// expected-error@+1 {{expected end of line in preprocessor expression}} +#if 1, 2, 3 +#endif + +// Test 5: Comma in #elif +#if 0 +#elif (1, 2) // expected-error {{comma operator in operand of #if}} +#endif + +// Test 6: Leading comma (syntax error) +// expected-error@+1 {{invalid token at start of a preprocessor expression}} +#if , +#endif + +// Test 7: Comma in #embed limit parameter (C++23+) +#if __cplusplus >= 202302L +// since-cxx23-error@+1 {{expected ')'}} +#embed "jk.txt" limit(1, 2) +#endif diff --git a/clang/test/SemaCXX/alloc-token.cpp b/clang/test/SemaCXX/alloc-token.cpp new file mode 100644 index 0000000..be7acb7 --- /dev/null +++ b/clang/test/SemaCXX/alloc-token.cpp @@ -0,0 +1,79 @@ +// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++23 -fsyntax-only -verify %s +// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++23 -fsyntax-only -verify %s -fexperimental-new-constant-interpreter +// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++23 -fsyntax-only -verify %s -falloc-token-mode=typehash -DMODE_TYPEHASH +// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++23 -fsyntax-only -verify %s -falloc-token-max=2 -DTOKEN_MAX=2 + +#if !__has_builtin(__builtin_infer_alloc_token) +#error "missing __builtin_infer_alloc_token" +#endif + +struct NoPtr { + int x; + long y; +}; + +struct WithPtr { + int a; + char *buf; +}; + +// Check specific known values; these are guaranteed to be stable. +#ifdef MODE_TYPEHASH +static_assert(__builtin_infer_alloc_token(sizeof(int)) == 2689373973731826898ULL); +static_assert(__builtin_infer_alloc_token(sizeof(char*)) == 2250492667400517147ULL); +static_assert(__builtin_infer_alloc_token(sizeof(NoPtr)) == 7465259095297095368ULL); +static_assert(__builtin_infer_alloc_token(sizeof(WithPtr)) == 11898882936532569145ULL); +#elif defined(TOKEN_MAX) +# if TOKEN_MAX == 2 +static_assert(__builtin_infer_alloc_token(sizeof(int)) == 0); +static_assert(__builtin_infer_alloc_token(sizeof(char*)) == 1); +static_assert(__builtin_infer_alloc_token(sizeof(NoPtr)) == 0); +static_assert(__builtin_infer_alloc_token(sizeof(WithPtr)) == 1); +# else +# error "unhandled TOKEN_MAX case" +# endif +#else +static_assert(__builtin_infer_alloc_token(sizeof(int)) == 2689373973731826898ULL); +static_assert(__builtin_infer_alloc_token(sizeof(char*)) == 11473864704255292954ULL); +static_assert(__builtin_infer_alloc_token(sizeof(NoPtr)) == 7465259095297095368ULL); +static_assert(__builtin_infer_alloc_token(sizeof(WithPtr)) == 11898882936532569145ULL); +#endif + +// Template function. +template <typename T> +constexpr unsigned long get_token() { + return __builtin_infer_alloc_token(sizeof(T)); +} +static_assert(__builtin_infer_alloc_token(sizeof(int)) == get_token<int>()); + +// Test complex expressions. +static_assert(__builtin_constant_p(__builtin_infer_alloc_token(sizeof(int)))); +static_assert(__builtin_infer_alloc_token(sizeof(NoPtr) * 2, 1) == get_token<NoPtr>()); +static_assert(__builtin_infer_alloc_token(1, 4 + sizeof(NoPtr)) == get_token<NoPtr>()); +static_assert(__builtin_infer_alloc_token(sizeof(NoPtr) << 8) == get_token<NoPtr>()); + +// Test usable as a template param. +template <unsigned long ID, typename T> +struct token_for_type { + static_assert(ID == get_token<T>()); + static constexpr unsigned long value = ID; +}; +static_assert(token_for_type<__builtin_infer_alloc_token(sizeof(int)), int>::value == get_token<int>()); + +template <typename T = void> +void template_test() { + __builtin_infer_alloc_token(T()); // no error if not instantiated +} + +template <typename T> +void negative_template_test() { + __builtin_infer_alloc_token(T()); // expected-error {{argument may not have 'void' type}} +} + +void negative_tests() { + __builtin_infer_alloc_token(); // expected-error {{too few arguments to function call}} + __builtin_infer_alloc_token((void)0); // expected-error {{argument may not have 'void' type}} + negative_template_test<void>(); // expected-note {{in instantiation of function template specialization 'negative_template_test<void>' requested here}} + constexpr auto inference_fail = __builtin_infer_alloc_token(123); // expected-error {{must be initialized by a constant expression}} \ + // expected-note {{could not infer allocation type for __builtin_infer_alloc_token}} +} diff --git a/clang/test/SemaHLSL/Semantics/entry_parameter.hlsl b/clang/test/SemaHLSL/Semantics/entry_parameter.hlsl index 393d730..bcc94f0 100644 --- a/clang/test/SemaHLSL/Semantics/entry_parameter.hlsl +++ b/clang/test/SemaHLSL/Semantics/entry_parameter.hlsl @@ -11,4 +11,9 @@ void CSMain(int GI : SV_GroupIndex, uint ID : SV_DispatchThreadID, uint GID : SV // CHECK-NEXT: HLSLSV_GroupIDAttr // CHECK-NEXT: ParmVarDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:96 GThreadID 'uint' // CHECK-NEXT: HLSLSV_GroupThreadIDAttr + +// CHECK: HLSLSV_GroupIndexAttr 0x{{[0-9a-fA-F]+}} <{{.*}}> ParmVar 0x{{[0-9a-fA-F]+}} 'GI' 'int' 0 +// CHECK-NEXT: HLSLSV_DispatchThreadIDAttr 0x{{[0-9a-fA-F]+}} <{{.*}}> ParmVar 0x{{[0-9a-fA-F]+}} 'ID' 'uint':'unsigned int' 0 +// CHECK-NEXT: HLSLSV_GroupIDAttr 0x{{[0-9a-fA-F]+}} <{{.*}}> ParmVar 0x{{[0-9a-fA-F]+}} 'GID' 'uint':'unsigned int' 0 +// CHECK-NEXT: HLSLSV_GroupThreadIDAttr 0x{{[0-9a-fA-F]+}} <{{.*}}> ParmVar 0x{{[0-9a-fA-F]+}} 'GThreadID' 'uint':'unsigned int' 0 } diff --git a/clang/test/SemaHLSL/Semantics/position.ps.hlsl b/clang/test/SemaHLSL/Semantics/position.ps.hlsl index 32bc5f5..27a8e4a 100644 --- a/clang/test/SemaHLSL/Semantics/position.ps.hlsl +++ b/clang/test/SemaHLSL/Semantics/position.ps.hlsl @@ -1,7 +1,10 @@ // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-pixel -x hlsl -finclude-default-header -o - %s -ast-dump | FileCheck %s -float4 main(float4 a : SV_Position) { +// FIXME(Keenuts): add mandatory output semantic once those are implemented. +float4 main(float4 a : SV_Position2) { // CHECK: FunctionDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> line:[[@LINE-1]]:8 main 'float4 (float4)' // CHECK-NEXT: ParmVarDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:20 a 'float4':'vector<float, 4>' // CHECK-NEXT: HLSLSV_PositionAttr 0x{{[0-9a-fA-F]+}} <{{.*}}> + +// CHECK: HLSLSV_PositionAttr 0x{{[0-9a-fA-F]+}} <{{.*}}> ParmVar 0x{{[0-9a-fA-F]+}} 'a' 'float4':'vector<float, 4>' 2 SemanticExplicitIndex } diff --git a/clang/test/SemaHLSL/Semantics/position.ps.struct.hlsl b/clang/test/SemaHLSL/Semantics/position.ps.struct.hlsl new file mode 100644 index 0000000..9f57231 --- /dev/null +++ b/clang/test/SemaHLSL/Semantics/position.ps.struct.hlsl @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-pixel -x hlsl -finclude-default-header -o - %s -ast-dump | FileCheck %s + +struct S { + float4 f0 : SV_Position; +// CHECK: FieldDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:10 f0 'float4':'vector<float, 4>' +// CHECK: HLSLSV_PositionAttr 0x{{[0-9a-fA-F]+}} <col:15> <<<NULL>>> 0 + float4 f1 : SV_Position3; +// CHECK: FieldDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:10 f1 'float4':'vector<float, 4>' +// CHECK: HLSLSV_PositionAttr 0x{{[0-9a-fA-F]+}} <col:15> <<<NULL>>> 3 SemanticExplicitIndex +}; + +// FIXME(Keenuts): add mandatory output semantic once those are implemented. +float4 main(S s) { +// CHECK: FunctionDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> line:[[@LINE-1]]:8 main 'float4 (S)' +// CHECK-NEXT: ParmVarDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:15 s 'S' + +// CHECK: HLSLSV_PositionAttr 0x{{[0-9a-fA-F]+}} <{{.*}}> Field 0x{{[0-9a-fA-F]+}} 'f0' 'float4':'vector<float, 4>' 0 +// CHECK: HLSLSV_PositionAttr 0x{{[0-9a-fA-F]+}} <{{.*}}> Field 0x{{[0-9a-fA-F]+}} 'f1' 'float4':'vector<float, 4>' 3 SemanticExplicitIndex +} diff --git a/clang/test/SemaHLSL/Semantics/struct_input.hlsl b/clang/test/SemaHLSL/Semantics/struct_input.hlsl new file mode 100644 index 0000000..66cab95 --- /dev/null +++ b/clang/test/SemaHLSL/Semantics/struct_input.hlsl @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -finclude-default-header -o - %s -verify + +struct S { + float4 f0 : SV_Position; +// expected-error@+2 {{semantic annotations must be present for all parameters of an entry function or patch constant function}} +// expected-note@+1 {{'f1' used here}} + float4 f1; +}; + +[shader("pixel")] +// expected-note@+1 {{'s' declared here}} +void main(S s) { +} + +[shader("pixel")] +// expected-error@+2 {{semantic annotations must be present for all parameters of an entry function or patch constant function}} +// expected-note@+1 {{'f' declared here}} +void main2(float4 p : SV_POSITION, float4 f) +{ } diff --git a/clang/test/SemaOpenMP/openmp-begin-declare-variant_template.cpp b/clang/test/SemaOpenMP/openmp-begin-declare-variant_template.cpp new file mode 100644 index 0000000..ded8f58 --- /dev/null +++ b/clang/test/SemaOpenMP/openmp-begin-declare-variant_template.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -triple x86_64 -fopenmp -verify %s + +// FIXME: Is this supposed to work? + +#pragma omp begin declare variant match(implementation={extension(allow_templates)}) +template <class T> void f(T) {} +// expected-note@-1 {{explicit instantiation refers here}} +#pragma end +template <int> struct A {}; +template <bool B> A<B> f() = delete; +template void f<float>(float); +// expected-error@-1 {{explicit instantiation of undefined function template 'f'}} diff --git a/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.cpp b/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.cpp index 4bb09d3..425beb9 100644 --- a/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.cpp +++ b/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.cpp @@ -2871,6 +2871,110 @@ TEST_P(UncheckedStatusOrAccessModelTest, EqualityCheck) { )cc"); } +TEST_P(UncheckedStatusOrAccessModelTest, PointerEqualityCheck) { + ExpectDiagnosticsFor( + R"cc( +#include "unchecked_statusor_access_test_defs.h" + + void target(STATUSOR_INT* x, STATUSOR_INT* y) { + if (x->ok()) { + if (x == y) + y->value(); + else + y->value(); // [[unsafe]] + } + } + )cc"); + ExpectDiagnosticsFor( + R"cc( +#include "unchecked_statusor_access_test_defs.h" + + void target(STATUSOR_INT* x, STATUSOR_INT* y) { + if (x->ok()) { + if (x != y) + y->value(); // [[unsafe]] + else + y->value(); + } + } + )cc"); + ExpectDiagnosticsFor( + R"cc( +#include "unchecked_statusor_access_test_defs.h" + + void target(STATUS* x, STATUS* y) { + auto sor = Make<STATUSOR_INT>(); + if (x->ok()) { + if (x == y && sor.status() == *y) + sor.value(); + else + sor.value(); // [[unsafe]] + } + } + )cc"); + ExpectDiagnosticsFor( + R"cc( +#include "unchecked_statusor_access_test_defs.h" + + void target(STATUS* x, STATUS* y) { + auto sor = Make<STATUSOR_INT>(); + if (x->ok()) { + if (x != y) + sor.value(); // [[unsafe]] + else if (sor.status() == *y) + sor.value(); + } + } + )cc"); +} + +TEST_P(UncheckedStatusOrAccessModelTest, Emplace) { + ExpectDiagnosticsFor(R"cc( +#include "unchecked_statusor_access_test_defs.h" + + struct Foo { + Foo(int); + }; + + void target(absl::StatusOr<Foo> sor, int value) { + sor.emplace(value); + sor.value(); + } + )cc"); + ExpectDiagnosticsFor(R"cc( +#include "unchecked_statusor_access_test_defs.h" + + struct Foo { + Foo(std::initializer_list<int>, int); + }; + + void target(absl::StatusOr<Foo> sor, int value) { + sor.emplace({1, 2, 3}, value); + sor.value(); + } + )cc"); + ExpectDiagnosticsFor(R"cc( +#include "unchecked_statusor_access_test_defs.h" + + void target() { + STATUSOR_INT sor; + bool sor_ok = sor.ok(); + if (!sor_ok) + sor.emplace(42); + sor.value(); + } + )cc"); + ExpectDiagnosticsFor(R"cc( +#include "unchecked_statusor_access_test_defs.h" + + void target(bool b) { + STATUSOR_INT sor; + if (b) sor.emplace(42); + if (b) sor.value(); + } + )cc"); +} + } // namespace std::string diff --git a/clang/unittests/Format/FormatTestObjC.cpp b/clang/unittests/Format/FormatTestObjC.cpp index 700d7cf8..cf8143a 100644 --- a/clang/unittests/Format/FormatTestObjC.cpp +++ b/clang/unittests/Format/FormatTestObjC.cpp @@ -949,6 +949,12 @@ TEST_F(FormatTestObjC, FormatObjCMethodExpr) { "[aaaaaaaaaaaaaaaaaaaaaaaaa\n" " aaaaaaaaaaaaaaaaa:aaaaaaaa\n" " aaa:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa];"); + verifyFormat("[objectName\n" + " respondsToSelector:\n" + " @selector(\n" + " somelonglonglonglongnameeeeeeee:\n" + " loooooooooanotherlonglonglonglongnametopush:\n" + " otherlongnameforlimit:)];"); Style = getChromiumStyle(FormatStyle::LK_ObjC); Style.ColumnLimit = 80; diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp index 1342e1a..183952a 100644 --- a/clang/utils/TableGen/ClangAttrEmitter.cpp +++ b/clang/utils/TableGen/ClangAttrEmitter.cpp @@ -3078,6 +3078,17 @@ static void emitAttributes(const RecordKeeper &Records, raw_ostream &OS, OS << " {\n"; + // The generator puts the arguments for each attribute in the child class, + // even if those are set in the inherited attribute class (in the TD + // file). This means I cannot access those from the parent class, and have + // to do this weirdness. Maybe the generator should be changed to + // arguments are put in the class they are declared in inside the TD file? + if (HLSLSemantic) { + OS << " if (SemanticExplicitIndex)\n"; + OS << " setSemanticIndex(SemanticIndex);\n"; + OS << " setTargetDecl(Target);\n"; + } + for (auto const &ai : Args) { if (!shouldEmitArg(ai)) continue; |