Mercurial > hg > CbC > CbC_llvm
changeset 129:9ec641e857f8
Fix compile error to update llvm 5.0
author | mir3636 |
---|---|
date | Tue, 12 Dec 2017 19:42:58 +0900 |
parents | c347d3398279 |
children | cc94f0a83282 |
files | tools/clang/include/clang/Serialization/ASTBitCodes.h tools/clang/lib/CodeGen/BackendUtil.cpp tools/clang/lib/CodeGen/CGCall.cpp tools/clang/lib/Driver/Types.cpp tools/clang/lib/Frontend/CompilerInvocation.cpp tools/clang/lib/Parse/ParseCbC.cpp tools/clang/lib/Sema/DeclSpec.cpp |
diffstat | 7 files changed, 3304 insertions(+), 1221 deletions(-) [+] |
line wrap: on
line diff
--- a/tools/clang/include/clang/Serialization/ASTBitCodes.h Wed Dec 06 14:37:17 2017 +0900 +++ b/tools/clang/include/clang/Serialization/ASTBitCodes.h Tue Dec 12 19:42:58 2017 +0900 @@ -175,6 +175,12 @@ : Begin(R.getBegin().getRawEncoding()), End(R.getEnd().getRawEncoding()), BitOffset(BitOffset) { } + SourceLocation getBegin() const { + return SourceLocation::getFromRawEncoding(Begin); + } + SourceLocation getEnd() const { + return SourceLocation::getFromRawEncoding(End); + } }; /// \brief Source range/offset of a preprocessed entity. @@ -191,6 +197,9 @@ void setLocation(SourceLocation L) { Loc = L.getRawEncoding(); } + SourceLocation getLocation() const { + return SourceLocation::getFromRawEncoding(Loc); + } }; /// \brief The number of predefined preprocessed entity IDs. @@ -217,7 +226,7 @@ /// \brief The block containing the detailed preprocessing record. PREPROCESSOR_DETAIL_BLOCK_ID, - + /// \brief The block containing the submodule structure. SUBMODULE_BLOCK_ID, @@ -244,6 +253,12 @@ /// \brief A block containing a module file extension. EXTENSION_BLOCK_ID, + + /// A block with unhashed content. + /// + /// These records should not change the \a ASTFileSignature. See \a + /// UnhashedControlBlockRecordTypes for the list of records. + UNHASHED_CONTROL_BLOCK_ID, }; /// \brief Record types that occur within the control block. @@ -279,9 +294,6 @@ /// AST file. MODULE_MAP_FILE, - /// \brief Record code for the signature that identifiers this AST file. - SIGNATURE, - /// \brief Record code for the module build directory. MODULE_DIRECTORY, }; @@ -300,9 +312,6 @@ /// \brief Record code for the target options table. TARGET_OPTIONS, - /// \brief Record code for the diagnostic options table. - DIAGNOSTIC_OPTIONS, - /// \brief Record code for the filesystem options table. FILE_SYSTEM_OPTIONS, @@ -313,6 +322,18 @@ PREPROCESSOR_OPTIONS, }; + /// Record codes for the unhashed control block. + enum UnhashedControlBlockRecordTypes { + /// Record code for the signature that identifiers this AST file. + SIGNATURE = 1, + + /// Record code for the diagnostic options table. + DIAGNOSTIC_OPTIONS, + + /// Record code for \#pragma diagnostic mappings. + DIAG_PRAGMA_MAPPINGS, + }; + /// \brief Record code for extension blocks. enum ExtensionBlockRecordTypes { /// Metadata describing this particular extension. @@ -335,7 +356,7 @@ /// /// The TYPE_OFFSET constant describes the record that occurs /// within the AST block. The record itself is an array of offsets that - /// point into the declarations and types block (identified by + /// point into the declarations and types block (identified by /// DECLTYPES_BLOCK_ID). The index into the array is based on the ID /// of a type. For a given type ID @c T, the lower three bits of /// @c T are its qualifiers (const, volatile, restrict), as in @@ -437,10 +458,10 @@ /// \brief Record code for the set of ext_vector type names. EXT_VECTOR_DECLS = 16, - + /// \brief Record code for the array of unused file scoped decls. UNUSED_FILESCOPED_DECLS = 17, - + /// \brief Record code for the table of offsets to entries in the /// preprocessing record. PPD_ENTITIES_OFFSETS = 18, @@ -456,7 +477,7 @@ /// \brief Record code for an update to the TU's lexically contained /// declarations. TU_UPDATE_LEXICAL = 22, - + // ID 23 used to be for a list of local redeclarations. /// \brief Record code for declarations that Sema keeps references of. @@ -468,12 +489,7 @@ /// \brief Record code for pending implicit instantiations. PENDING_IMPLICIT_INSTANTIATIONS = 26, - /// \brief Record code for a decl replacement block. - /// - /// If a declaration is modified after having been deserialized, and then - /// written to a dependent AST file, its ID and offset must be added to - /// the replacement block. - DECL_REPLACEMENTS = 27, + // ID 27 used to be for a list of replacement decls. /// \brief Record code for an update to a decl context's lookup table. /// @@ -484,20 +500,16 @@ /// that were modified after being deserialized and need updates. DECL_UPDATE_OFFSETS = 29, - /// \brief Record of updates for a declaration that was modified after - /// being deserialized. - DECL_UPDATES = 30, - - /// \brief Record code for the table of offsets to CXXBaseSpecifier - /// sets. - CXX_BASE_SPECIFIER_OFFSETS = 31, + // ID 30 used to be a decl update record. These are now in the DECLTYPES + // block. - /// \brief Record code for \#pragma diagnostic mappings. - DIAG_PRAGMA_MAPPINGS = 32, + // ID 31 used to be a list of offsets to DECL_CXX_BASE_SPECIFIERS records. + + // ID 32 used to be the code for \#pragma diagnostic mappings. /// \brief Record code for special CUDA declarations. CUDA_SPECIAL_DECL_REFS = 33, - + /// \brief Record code for header search information. HEADER_SEARCH_TABLE = 34, @@ -515,7 +527,7 @@ KNOWN_NAMESPACES = 38, /// \brief Record code for the remapping information used to relate - /// loaded modules to the various offsets and IDs(e.g., source location + /// loaded modules to the various offsets and IDs(e.g., source location /// offests, declaration and type IDs) that are used in that module to /// refer to other modules. MODULE_OFFSET_MAP = 39, @@ -524,20 +536,20 @@ /// which stores information about \#line directives. SOURCE_MANAGER_LINE_TABLE = 40, - /// \brief Record code for map of Objective-C class definition IDs to the + /// \brief Record code for map of Objective-C class definition IDs to the /// ObjC categories in a module that are attached to that class. OBJC_CATEGORIES_MAP = 41, /// \brief Record code for a file sorted array of DeclIDs in a module. FILE_SORTED_DECLS = 42, - + /// \brief Record code for an array of all of the (sub)modules that were /// imported by the AST file. IMPORTED_MODULES = 43, - + // ID 44 used to be a table of merged canonical declarations. // ID 45 used to be a list of declaration IDs of local redeclarations. - + /// \brief Record code for the array of Objective-C categories (including /// extensions). /// @@ -570,12 +582,34 @@ /// \brief Record code for potentially unused local typedef names. UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES = 52, - /// \brief Record code for the table of offsets to CXXCtorInitializers - /// lists. - CXX_CTOR_INITIALIZERS_OFFSETS = 53, + // ID 53 used to be a table of constructor initializer records. /// \brief Delete expressions that will be analyzed later. - DELETE_EXPRS_TO_ANALYZE = 54 + DELETE_EXPRS_TO_ANALYZE = 54, + + /// \brief Record code for \#pragma ms_struct options. + MSSTRUCT_PRAGMA_OPTIONS = 55, + + /// \brief Record code for \#pragma ms_struct options. + POINTERS_TO_MEMBERS_PRAGMA_OPTIONS = 56, + + /// \brief Number of unmatched #pragma clang cuda_force_host_device begin + /// directives we've seen. + CUDA_PRAGMA_FORCE_HOST_DEVICE_DEPTH = 57, + + /// \brief Record code for types associated with OpenCL extensions. + OPENCL_EXTENSION_TYPES = 58, + + /// \brief Record code for declarations associated with OpenCL extensions. + OPENCL_EXTENSION_DECLS = 59, + + MODULAR_CODEGEN_DECLS = 60, + + /// \brief Record code for \#pragma pack options. + PACK_PRAGMA_OPTIONS = 61, + + /// \brief The stack of open #ifs/#ifdefs recorded in a preamble. + PP_CONDITIONAL_STACK = 62, }; /// \brief Record types used within a source manager block. @@ -591,9 +625,12 @@ /// SM_SLOC_BUFFER_ENTRY record or a SM_SLOC_FILE_ENTRY with an /// overridden buffer. SM_SLOC_BUFFER_BLOB = 3, + /// \brief Describes a zlib-compressed blob that contains the data for + /// a buffer entry. + SM_SLOC_BUFFER_BLOB_COMPRESSED = 4, /// \brief Describes a source location entry (SLocEntry) for a /// macro expansion. - SM_SLOC_EXPANSION_ENTRY = 4 + SM_SLOC_EXPANSION_ENTRY = 5 }; /// \brief Record types used within a preprocessor block. @@ -676,6 +713,12 @@ /// \brief Specifies a header that is private to this submodule but /// must be textually included. SUBMODULE_PRIVATE_TEXTUAL_HEADER = 15, + /// \brief Specifies some declarations with initializers that must be + /// emitted to initialize the module. + SUBMODULE_INITIALIZERS = 16, + /// \brief Specifies the name of the module that will eventually + /// re-export the entities in this module. + SUBMODULE_EXPORT_AS = 17, }; /// \brief Record types used within a comments block. @@ -772,48 +815,30 @@ PREDEF_TYPE_PSEUDO_OBJECT = 35, /// \brief The placeholder type for builtin functions. PREDEF_TYPE_BUILTIN_FN = 36, - /// \brief OpenCL 1d image type. - PREDEF_TYPE_IMAGE1D_ID = 37, - /// \brief OpenCL 1d image array type. - PREDEF_TYPE_IMAGE1D_ARR_ID = 38, - /// \brief OpenCL 1d image buffer type. - PREDEF_TYPE_IMAGE1D_BUFF_ID = 39, - /// \brief OpenCL 2d image type. - PREDEF_TYPE_IMAGE2D_ID = 40, - /// \brief OpenCL 2d image array type. - PREDEF_TYPE_IMAGE2D_ARR_ID = 41, - /// \brief OpenCL 2d image depth type. - PREDEF_TYPE_IMAGE2D_DEP_ID = 42, - /// \brief OpenCL 2d image array depth type. - PREDEF_TYPE_IMAGE2D_ARR_DEP_ID = 43, - /// \brief OpenCL 2d image MSAA type. - PREDEF_TYPE_IMAGE2D_MSAA_ID = 44, - /// \brief OpenCL 2d image array MSAA type. - PREDEF_TYPE_IMAGE2D_ARR_MSAA_ID = 45, - /// \brief OpenCL 2d image MSAA depth type. - PREDEF_TYPE_IMAGE2D_MSAA_DEP_ID = 46, - /// \brief OpenCL 2d image array MSAA depth type. - PREDEF_TYPE_IMAGE2D_ARR_MSAA_DEPTH_ID = 47, - /// \brief OpenCL 3d image type. - PREDEF_TYPE_IMAGE3D_ID = 48, /// \brief OpenCL event type. - PREDEF_TYPE_EVENT_ID = 49, + PREDEF_TYPE_EVENT_ID = 37, /// \brief OpenCL clk event type. - PREDEF_TYPE_CLK_EVENT_ID = 50, + PREDEF_TYPE_CLK_EVENT_ID = 38, /// \brief OpenCL sampler type. - PREDEF_TYPE_SAMPLER_ID = 51, + PREDEF_TYPE_SAMPLER_ID = 39, /// \brief OpenCL queue type. - PREDEF_TYPE_QUEUE_ID = 52, - /// \brief OpenCL ndrange type. - PREDEF_TYPE_NDRANGE_ID = 53, + PREDEF_TYPE_QUEUE_ID = 40, /// \brief OpenCL reserve_id type. - PREDEF_TYPE_RESERVE_ID_ID = 54, + PREDEF_TYPE_RESERVE_ID_ID = 41, /// \brief The placeholder type for OpenMP array section. - PREDEF_TYPE_OMP_ARRAY_SECTION = 55 + PREDEF_TYPE_OMP_ARRAY_SECTION = 42, + /// \brief The '__float128' type + PREDEF_TYPE_FLOAT128_ID = 43, + /// \brief The '_Float16' type + PREDEF_TYPE_FLOAT16_ID = 44, #ifndef noCbC /// \brief The __code type. - ,PREDEF_TYPE___CODE_ID = 56 + PREDEF_TYPE___CODE_ID = 45, #endif + /// \brief OpenCL image types with auto numeration +#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ + PREDEF_TYPE_##Id##_ID, +#include "clang/Basic/OpenCLImageTypes.def" }; /// \brief The number of predefined type IDs that are reserved for @@ -828,7 +853,7 @@ /// These constants describe the type records that can occur within a /// block identified by DECLTYPES_BLOCK_ID in the AST file. Each /// constant describes a record for a specific type class in the - /// AST. + /// AST. Note that DeclCode values share this code space. enum TypeCode { /// \brief An ExtQualType record. TYPE_EXT_QUAL = 1, @@ -913,7 +938,15 @@ /// \brief An AdjustedType record. TYPE_ADJUSTED = 42, /// \brief A PipeType record. - TYPE_PIPE = 43 + TYPE_PIPE = 43, + /// \brief An ObjCTypeParamType record. + TYPE_OBJC_TYPE_PARAM = 44, + /// \brief A DeducedTemplateSpecializationType record. + TYPE_DEDUCED_TEMPLATE_SPECIALIZATION = 45, + /// \brief A DependentSizedExtVectorType record. + TYPE_DEPENDENT_SIZED_EXT_VECTOR = 46, + /// \brief A DependentAddressSpaceType record. + TYPE_DEPENDENT_ADDRESS_SPACE = 47 }; /// \brief The type IDs for special types constructed by semantic @@ -991,23 +1024,37 @@ /// \brief The internal '__make_integer_seq' template. PREDEF_DECL_MAKE_INTEGER_SEQ_ID = 13, + + /// \brief The internal '__NSConstantString' typedef. + PREDEF_DECL_CF_CONSTANT_STRING_ID = 14, + + /// \brief The internal '__NSConstantString' tag type. + PREDEF_DECL_CF_CONSTANT_STRING_TAG_ID = 15, + + /// \brief The internal '__type_pack_element' template. + PREDEF_DECL_TYPE_PACK_ELEMENT_ID = 16, }; /// \brief The number of declaration IDs that are predefined. /// /// For more information about predefined declarations, see the /// \c PredefinedDeclIDs type and the PREDEF_DECL_*_ID constants. - const unsigned int NUM_PREDEF_DECL_IDS = 14; + const unsigned int NUM_PREDEF_DECL_IDS = 17; + + /// \brief Record of updates for a declaration that was modified after + /// being deserialized. This can occur within DECLTYPES_BLOCK_ID. + const unsigned int DECL_UPDATES = 49; /// \brief Record code for a list of local redeclarations of a declaration. + /// This can occur within DECLTYPES_BLOCK_ID. const unsigned int LOCAL_REDECLARATIONS = 50; /// \brief Record codes for each kind of declaration. /// /// These constants describe the declaration records that can occur within - /// a declarations block (identified by DECLS_BLOCK_ID). Each + /// a declarations block (identified by DECLTYPES_BLOCK_ID). Each /// constant describes a record for a specific declaration class - /// in the AST. + /// in the AST. Note that TypeCode values share this code space. enum DeclCode { /// \brief A TypedefDecl record. DECL_TYPEDEF = 51, @@ -1053,6 +1100,10 @@ DECL_IMPLICIT_PARAM, /// \brief A ParmVarDecl record. DECL_PARM_VAR, + /// \brief A DecompositionDecl record. + DECL_DECOMPOSITION, + /// \brief A BindingDecl record. + DECL_BINDING, /// \brief A FileScopeAsmDecl record. DECL_FILE_SCOPE_ASM, /// \brief A BlockDecl record. @@ -1084,8 +1135,12 @@ DECL_NAMESPACE_ALIAS, /// \brief A UsingDecl record. DECL_USING, + /// \brief A UsingPackDecl record. + DECL_USING_PACK, /// \brief A UsingShadowDecl record. DECL_USING_SHADOW, + /// \brief A ConstructorUsingShadowDecl record. + DECL_CONSTRUCTOR_USING_SHADOW, /// \brief A UsingDirecitveDecl record. DECL_USING_DIRECTIVE, /// \brief An UnresolvedUsingValueDecl record. @@ -1094,12 +1149,18 @@ DECL_UNRESOLVED_USING_TYPENAME, /// \brief A LinkageSpecDecl record. DECL_LINKAGE_SPEC, + /// \brief An ExportDecl record. + DECL_EXPORT, /// \brief A CXXRecordDecl record. DECL_CXX_RECORD, + /// \brief A CXXDeductionGuideDecl record. + DECL_CXX_DEDUCTION_GUIDE, /// \brief A CXXMethodDecl record. DECL_CXX_METHOD, /// \brief A CXXConstructorDecl record. DECL_CXX_CONSTRUCTOR, + /// \brief A CXXConstructorDecl record for an inherited constructor. + DECL_CXX_INHERITED_CONSTRUCTOR, /// \brief A CXXDestructorDecl record. DECL_CXX_DESTRUCTOR, /// \brief A CXXConversionDecl record. @@ -1158,6 +1219,14 @@ DECL_EMPTY, /// \brief An ObjCTypeParamDecl record. DECL_OBJC_TYPE_PARAM, + /// \brief An OMPCapturedExprDecl record. + DECL_OMP_CAPTUREDEXPR, + /// \brief A PragmaCommentDecl record. + DECL_PRAGMA_COMMENT, + /// \brief A PragmaDetectMismatchDecl record. + DECL_PRAGMA_DETECT_MISMATCH, + /// \brief An OMPDeclareReductionDecl record. + DECL_OMP_DECLARE_REDUCTION, }; /// \brief Record codes for each kind of statement or expression. @@ -1265,10 +1334,14 @@ EXPR_DESIGNATED_INIT, /// \brief A DesignatedInitUpdateExpr record. EXPR_DESIGNATED_INIT_UPDATE, + /// \brief An NoInitExpr record. + EXPR_NO_INIT, + /// \brief An ArrayInitLoopExpr record. + EXPR_ARRAY_INIT_LOOP, + /// \brief An ArrayInitIndexExpr record. + EXPR_ARRAY_INIT_INDEX, /// \brief An ImplicitValueInitExpr record. EXPR_IMPLICIT_VALUE_INIT, - /// \brief An NoInitExpr record. - EXPR_NO_INIT, /// \brief A VAArgExpr record. EXPR_VA_ARG, /// \brief An AddrLabelExpr record. @@ -1337,8 +1410,10 @@ STMT_OBJC_AT_THROW, /// \brief An ObjCAutoreleasePoolStmt record. STMT_OBJC_AUTORELEASE_POOL, - /// \brief A ObjCBoolLiteralExpr record. + /// \brief An ObjCBoolLiteralExpr record. EXPR_OBJC_BOOL_LITERAL, + /// \brief An ObjCAvailabilityCheckExpr record. + EXPR_OBJC_AVAILABILITY_CHECK, // C++ @@ -1355,6 +1430,8 @@ EXPR_CXX_MEMBER_CALL, /// \brief A CXXConstructExpr record. EXPR_CXX_CONSTRUCT, + /// \brief A CXXInheritedCtorInitExpr record. + EXPR_CXX_INHERITED_CTOR_INIT, /// \brief A CXXTemporaryObjectExpr record. EXPR_CXX_TEMPORARY_OBJECT, /// \brief A CXXStaticCastExpr record. @@ -1451,6 +1528,8 @@ STMT_OMP_TARGET_DATA_DIRECTIVE, STMT_OMP_TARGET_ENTER_DATA_DIRECTIVE, STMT_OMP_TARGET_EXIT_DATA_DIRECTIVE, + STMT_OMP_TARGET_PARALLEL_DIRECTIVE, + STMT_OMP_TARGET_PARALLEL_FOR_DIRECTIVE, STMT_OMP_TEAMS_DIRECTIVE, STMT_OMP_TASKGROUP_DIRECTIVE, STMT_OMP_CANCELLATION_POINT_DIRECTIVE, @@ -1458,13 +1537,33 @@ STMT_OMP_TASKLOOP_DIRECTIVE, STMT_OMP_TASKLOOP_SIMD_DIRECTIVE, STMT_OMP_DISTRIBUTE_DIRECTIVE, + STMT_OMP_TARGET_UPDATE_DIRECTIVE, + STMT_OMP_DISTRIBUTE_PARALLEL_FOR_DIRECTIVE, + STMT_OMP_DISTRIBUTE_PARALLEL_FOR_SIMD_DIRECTIVE, + STMT_OMP_DISTRIBUTE_SIMD_DIRECTIVE, + STMT_OMP_TARGET_PARALLEL_FOR_SIMD_DIRECTIVE, + STMT_OMP_TARGET_SIMD_DIRECTIVE, + STMT_OMP_TEAMS_DISTRIBUTE_DIRECTIVE, + STMT_OMP_TEAMS_DISTRIBUTE_SIMD_DIRECTIVE, + STMT_OMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_DIRECTIVE, + STMT_OMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_DIRECTIVE, + STMT_OMP_TARGET_TEAMS_DIRECTIVE, + STMT_OMP_TARGET_TEAMS_DISTRIBUTE_DIRECTIVE, + STMT_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_DIRECTIVE, + STMT_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_DIRECTIVE, + STMT_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD_DIRECTIVE, EXPR_OMP_ARRAY_SECTION, // ARC EXPR_OBJC_BRIDGED_CAST, // ObjCBridgedCastExpr - + STMT_MS_DEPENDENT_EXISTS, // MSDependentExistsStmt - EXPR_LAMBDA // LambdaExpr + EXPR_LAMBDA, // LambdaExpr + STMT_COROUTINE_BODY, + STMT_CORETURN, + EXPR_COAWAIT, + EXPR_COYIELD, + EXPR_DEPENDENT_COAWAIT, }; /// \brief The kinds of designators that can occur in a @@ -1564,7 +1663,8 @@ IdentifierInfo *getIdentifier() const { assert(Kind == DeclarationName::Identifier || - Kind == DeclarationName::CXXLiteralOperatorName); + Kind == DeclarationName::CXXLiteralOperatorName || + Kind == DeclarationName::CXXDeductionGuideName); return (IdentifierInfo *)Data; } Selector getSelector() const {
--- a/tools/clang/lib/CodeGen/BackendUtil.cpp Wed Dec 06 14:37:17 2017 +0900 +++ b/tools/clang/lib/CodeGen/BackendUtil.cpp Tue Dec 12 19:42:58 2017 +0900 @@ -14,22 +14,30 @@ #include "clang/Frontend/CodeGenOptions.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Frontend/Utils.h" +#include "clang/Lex/HeaderSearchOptions.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/Triple.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TargetTransformInfo.h" +#include "llvm/Bitcode/BitcodeReader.h" +#include "llvm/Bitcode/BitcodeWriter.h" #include "llvm/Bitcode/BitcodeWriterPass.h" #include "llvm/CodeGen/RegAllocRegistry.h" #include "llvm/CodeGen/SchedulerRegistry.h" #include "llvm/IR/DataLayout.h" -#include "llvm/IR/FunctionInfo.h" #include "llvm/IR/IRPrintingPasses.h" #include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" +#include "llvm/IR/ModuleSummaryIndex.h" #include "llvm/IR/Verifier.h" +#include "llvm/LTO/LTOBackend.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/SubtargetFeature.h" -#include "llvm/Object/FunctionIndexObjectFile.h" +#include "llvm/Passes/PassBuilder.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/Timer.h" @@ -37,11 +45,16 @@ #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetSubtargetInfo.h" +#include "llvm/Transforms/Coroutines.h" #include "llvm/Transforms/IPO.h" +#include "llvm/Transforms/IPO/AlwaysInliner.h" #include "llvm/Transforms/IPO/PassManagerBuilder.h" +#include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h" #include "llvm/Transforms/Instrumentation.h" #include "llvm/Transforms/ObjCARC.h" #include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Scalar/GVN.h" +#include "llvm/Transforms/Utils/NameAnonGlobals.h" #include "llvm/Transforms/Utils/SymbolRewriter.h" #include <memory> using namespace clang; @@ -49,8 +62,12 @@ namespace { +// Default filename used for profile generation. +static constexpr StringLiteral DefaultProfileGenName = "default_%m.profraw"; + class EmitAssemblyHelper { DiagnosticsEngine &Diags; + const HeaderSearchOptions &HSOpts; const CodeGenOptions &CodeGenOpts; const clang::TargetOptions &TargetOpts; const LangOptions &LangOpts; @@ -58,11 +75,8 @@ Timer CodeGenerationTime; - mutable legacy::PassManager *CodeGenPasses; - mutable legacy::PassManager *PerModulePasses; - mutable legacy::FunctionPassManager *PerFunctionPasses; + std::unique_ptr<raw_pwrite_stream> OS; -private: TargetIRAnalysis getTargetIRAnalysis() const { if (TM) return TM->getTargetIRAnalysis(); @@ -70,86 +84,66 @@ return TargetIRAnalysis(); } - legacy::PassManager *getCodeGenPasses() const { - if (!CodeGenPasses) { - CodeGenPasses = new legacy::PassManager(); - CodeGenPasses->add( - createTargetTransformInfoWrapperPass(getTargetIRAnalysis())); - } - return CodeGenPasses; - } - - legacy::PassManager *getPerModulePasses() const { - if (!PerModulePasses) { - PerModulePasses = new legacy::PassManager(); - PerModulePasses->add( - createTargetTransformInfoWrapperPass(getTargetIRAnalysis())); - } - return PerModulePasses; - } - - legacy::FunctionPassManager *getPerFunctionPasses() const { - if (!PerFunctionPasses) { - PerFunctionPasses = new legacy::FunctionPassManager(TheModule); - PerFunctionPasses->add( - createTargetTransformInfoWrapperPass(getTargetIRAnalysis())); - } - return PerFunctionPasses; - } - - void CreatePasses(FunctionInfoIndex *FunctionIndex); + void CreatePasses(legacy::PassManager &MPM, legacy::FunctionPassManager &FPM); /// Generates the TargetMachine. - /// Returns Null if it is unable to create the target machine. + /// Leaves TM unchanged if it is unable to create the target machine. /// Some of our clang tests specify triples which are not built /// into clang. This is okay because these tests check the generated /// IR, and they require DataLayout which depends on the triple. /// In this case, we allow this method to fail and not report an error. /// When MustCreateTM is used, we print an error if we are unable to load /// the requested target. - TargetMachine *CreateTargetMachine(bool MustCreateTM); + void CreateTargetMachine(bool MustCreateTM); /// Add passes necessary to emit assembly or LLVM IR. /// /// \return True on success. - bool AddEmitPasses(BackendAction Action, raw_pwrite_stream &OS); + bool AddEmitPasses(legacy::PassManager &CodeGenPasses, BackendAction Action, + raw_pwrite_stream &OS); public: - EmitAssemblyHelper(DiagnosticsEngine &_Diags, const CodeGenOptions &CGOpts, + EmitAssemblyHelper(DiagnosticsEngine &_Diags, + const HeaderSearchOptions &HeaderSearchOpts, + const CodeGenOptions &CGOpts, const clang::TargetOptions &TOpts, const LangOptions &LOpts, Module *M) - : Diags(_Diags), CodeGenOpts(CGOpts), TargetOpts(TOpts), LangOpts(LOpts), - TheModule(M), CodeGenerationTime("Code Generation Time"), - CodeGenPasses(nullptr), PerModulePasses(nullptr), - PerFunctionPasses(nullptr) {} + : Diags(_Diags), HSOpts(HeaderSearchOpts), CodeGenOpts(CGOpts), + TargetOpts(TOpts), LangOpts(LOpts), TheModule(M), + CodeGenerationTime("codegen", "Code Generation Time") {} ~EmitAssemblyHelper() { - delete CodeGenPasses; - delete PerModulePasses; - delete PerFunctionPasses; if (CodeGenOpts.DisableFree) BuryPointer(std::move(TM)); } std::unique_ptr<TargetMachine> TM; - void EmitAssembly(BackendAction Action, raw_pwrite_stream *OS); + void EmitAssembly(BackendAction Action, + std::unique_ptr<raw_pwrite_stream> OS); + + void EmitAssemblyWithNewPassManager(BackendAction Action, + std::unique_ptr<raw_pwrite_stream> OS); }; // We need this wrapper to access LangOpts and CGOpts from extension functions // that we add to the PassManagerBuilder. class PassManagerBuilderWrapper : public PassManagerBuilder { public: - PassManagerBuilderWrapper(const CodeGenOptions &CGOpts, + PassManagerBuilderWrapper(const Triple &TargetTriple, + const CodeGenOptions &CGOpts, const LangOptions &LangOpts) - : PassManagerBuilder(), CGOpts(CGOpts), LangOpts(LangOpts) {} + : PassManagerBuilder(), TargetTriple(TargetTriple), CGOpts(CGOpts), + LangOpts(LangOpts) {} + const Triple &getTargetTriple() const { return TargetTriple; } const CodeGenOptions &getCGOpts() const { return CGOpts; } const LangOptions &getLangOpts() const { return LangOpts; } + private: + const Triple &TargetTriple; const CodeGenOptions &CGOpts; const LangOptions &LangOpts; }; - } static void addObjCARCAPElimPass(const PassManagerBuilder &Builder, PassManagerBase &PM) { @@ -173,7 +167,7 @@ } static void addBoundsCheckingPass(const PassManagerBuilder &Builder, - legacy::PassManagerBase &PM) { + legacy::PassManagerBase &PM) { PM.add(createBoundsCheckingPass()); } @@ -188,24 +182,56 @@ Opts.IndirectCalls = CGOpts.SanitizeCoverageIndirectCalls; Opts.TraceBB = CGOpts.SanitizeCoverageTraceBB; Opts.TraceCmp = CGOpts.SanitizeCoverageTraceCmp; + Opts.TraceDiv = CGOpts.SanitizeCoverageTraceDiv; + Opts.TraceGep = CGOpts.SanitizeCoverageTraceGep; Opts.Use8bitCounters = CGOpts.SanitizeCoverage8bitCounters; + Opts.TracePC = CGOpts.SanitizeCoverageTracePC; + Opts.TracePCGuard = CGOpts.SanitizeCoverageTracePCGuard; + Opts.NoPrune = CGOpts.SanitizeCoverageNoPrune; + Opts.Inline8bitCounters = CGOpts.SanitizeCoverageInline8bitCounters; + Opts.PCTable = CGOpts.SanitizeCoveragePCTable; + Opts.StackDepth = CGOpts.SanitizeCoverageStackDepth; PM.add(createSanitizerCoverageModulePass(Opts)); } +// Check if ASan should use GC-friendly instrumentation for globals. +// First of all, there is no point if -fdata-sections is off (expect for MachO, +// where this is not a factor). Also, on ELF this feature requires an assembler +// extension that only works with -integrated-as at the moment. +static bool asanUseGlobalsGC(const Triple &T, const CodeGenOptions &CGOpts) { + if (!CGOpts.SanitizeAddressGlobalsDeadStripping) + return false; + switch (T.getObjectFormat()) { + case Triple::MachO: + case Triple::COFF: + return true; + case Triple::ELF: + return CGOpts.DataSections && !CGOpts.DisableIntegratedAS; + default: + return false; + } +} + static void addAddressSanitizerPasses(const PassManagerBuilder &Builder, legacy::PassManagerBase &PM) { const PassManagerBuilderWrapper &BuilderWrapper = static_cast<const PassManagerBuilderWrapper&>(Builder); + const Triple &T = BuilderWrapper.getTargetTriple(); const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts(); bool Recover = CGOpts.SanitizeRecover.has(SanitizerKind::Address); - PM.add(createAddressSanitizerFunctionPass(/*CompileKernel*/false, Recover)); - PM.add(createAddressSanitizerModulePass(/*CompileKernel*/false, Recover)); + bool UseAfterScope = CGOpts.SanitizeAddressUseAfterScope; + bool UseGlobalsGC = asanUseGlobalsGC(T, CGOpts); + PM.add(createAddressSanitizerFunctionPass(/*CompileKernel*/ false, Recover, + UseAfterScope)); + PM.add(createAddressSanitizerModulePass(/*CompileKernel*/ false, Recover, + UseGlobalsGC)); } static void addKernelAddressSanitizerPasses(const PassManagerBuilder &Builder, legacy::PassManagerBase &PM) { - PM.add(createAddressSanitizerFunctionPass(/*CompileKernel*/true, - /*Recover*/true)); + PM.add(createAddressSanitizerFunctionPass( + /*CompileKernel*/ true, + /*Recover*/ true, /*UseAfterScope*/ false)); PM.add(createAddressSanitizerModulePass(/*CompileKernel*/true, /*Recover*/true)); } @@ -215,7 +241,9 @@ const PassManagerBuilderWrapper &BuilderWrapper = static_cast<const PassManagerBuilderWrapper&>(Builder); const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts(); - PM.add(createMemorySanitizerPass(CGOpts.SanitizeMemoryTrackOrigins)); + int TrackOrigins = CGOpts.SanitizeMemoryTrackOrigins; + bool Recover = CGOpts.SanitizeRecover.has(SanitizerKind::Memory); + PM.add(createMemorySanitizerPass(TrackOrigins, Recover)); // MemorySanitizer inserts complex instrumentation that mostly follows // the logic of the original code, but operates on "shadow" values. @@ -243,6 +271,19 @@ PM.add(createDataFlowSanitizerPass(LangOpts.SanitizerBlacklistFiles)); } +static void addEfficiencySanitizerPass(const PassManagerBuilder &Builder, + legacy::PassManagerBase &PM) { + const PassManagerBuilderWrapper &BuilderWrapper = + static_cast<const PassManagerBuilderWrapper&>(Builder); + const LangOptions &LangOpts = BuilderWrapper.getLangOpts(); + EfficiencySanitizerOptions Opts; + if (LangOpts.Sanitize.has(SanitizerKind::EfficiencyCacheFrag)) + Opts.ToolType = EfficiencySanitizerOptions::ESAN_CacheFrag; + else if (LangOpts.Sanitize.has(SanitizerKind::EfficiencyWorkingSet)) + Opts.ToolType = EfficiencySanitizerOptions::ESAN_WorkingSet; + PM.add(createEfficiencySanitizerPass(Opts)); +} + static TargetLibraryInfoImpl *createTLII(llvm::Triple &TargetTriple, const CodeGenOptions &CodeGenOpts) { TargetLibraryInfoImpl *TLII = new TargetLibraryInfoImpl(TargetTriple); @@ -250,7 +291,7 @@ TLII->disableAllFunctions(); else { // Disable individual libc/libm calls in TargetLibraryInfo. - LibFunc::Func F; + LibFunc F; for (auto &FuncName : CodeGenOpts.getNoBuiltinFuncs()) if (TLII->getLibFunc(FuncName, F)) TLII->setUnavailable(F); @@ -260,6 +301,9 @@ case CodeGenOptions::Accelerate: TLII->addVectorizableFunctionsFromVecLib(TargetLibraryInfoImpl::Accelerate); break; + case CodeGenOptions::SVML: + TLII->addVectorizableFunctionsFromVecLib(TargetLibraryInfoImpl::SVML); + break; default: break; } @@ -277,68 +321,199 @@ MPM->add(createRewriteSymbolsPass(DL)); } -void EmitAssemblyHelper::CreatePasses(FunctionInfoIndex *FunctionIndex) { +static CodeGenOpt::Level getCGOptLevel(const CodeGenOptions &CodeGenOpts) { + switch (CodeGenOpts.OptimizationLevel) { + default: + llvm_unreachable("Invalid optimization level!"); + case 0: + return CodeGenOpt::None; + case 1: + return CodeGenOpt::Less; + case 2: + return CodeGenOpt::Default; // O2/Os/Oz + case 3: + return CodeGenOpt::Aggressive; + } +} + +static Optional<llvm::CodeModel::Model> +getCodeModel(const CodeGenOptions &CodeGenOpts) { + unsigned CodeModel = llvm::StringSwitch<unsigned>(CodeGenOpts.CodeModel) + .Case("small", llvm::CodeModel::Small) + .Case("kernel", llvm::CodeModel::Kernel) + .Case("medium", llvm::CodeModel::Medium) + .Case("large", llvm::CodeModel::Large) + .Case("default", ~1u) + .Default(~0u); + assert(CodeModel != ~0u && "invalid code model!"); + if (CodeModel == ~1u) + return None; + return static_cast<llvm::CodeModel::Model>(CodeModel); +} + +static llvm::Reloc::Model getRelocModel(const CodeGenOptions &CodeGenOpts) { + // Keep this synced with the equivalent code in + // lib/Frontend/CompilerInvocation.cpp + llvm::Optional<llvm::Reloc::Model> RM; + RM = llvm::StringSwitch<llvm::Reloc::Model>(CodeGenOpts.RelocationModel) + .Case("static", llvm::Reloc::Static) + .Case("pic", llvm::Reloc::PIC_) + .Case("ropi", llvm::Reloc::ROPI) + .Case("rwpi", llvm::Reloc::RWPI) + .Case("ropi-rwpi", llvm::Reloc::ROPI_RWPI) + .Case("dynamic-no-pic", llvm::Reloc::DynamicNoPIC); + assert(RM.hasValue() && "invalid PIC model!"); + return *RM; +} + +static TargetMachine::CodeGenFileType getCodeGenFileType(BackendAction Action) { + if (Action == Backend_EmitObj) + return TargetMachine::CGFT_ObjectFile; + else if (Action == Backend_EmitMCNull) + return TargetMachine::CGFT_Null; + else { + assert(Action == Backend_EmitAssembly && "Invalid action!"); + return TargetMachine::CGFT_AssemblyFile; + } +} + +static void initTargetOptions(llvm::TargetOptions &Options, + const CodeGenOptions &CodeGenOpts, + const clang::TargetOptions &TargetOpts, + const LangOptions &LangOpts, + const HeaderSearchOptions &HSOpts) { + Options.ThreadModel = + llvm::StringSwitch<llvm::ThreadModel::Model>(CodeGenOpts.ThreadModel) + .Case("posix", llvm::ThreadModel::POSIX) + .Case("single", llvm::ThreadModel::Single); + + // Set float ABI type. + assert((CodeGenOpts.FloatABI == "soft" || CodeGenOpts.FloatABI == "softfp" || + CodeGenOpts.FloatABI == "hard" || CodeGenOpts.FloatABI.empty()) && + "Invalid Floating Point ABI!"); + Options.FloatABIType = + llvm::StringSwitch<llvm::FloatABI::ABIType>(CodeGenOpts.FloatABI) + .Case("soft", llvm::FloatABI::Soft) + .Case("softfp", llvm::FloatABI::Soft) + .Case("hard", llvm::FloatABI::Hard) + .Default(llvm::FloatABI::Default); + + // Set FP fusion mode. + switch (LangOpts.getDefaultFPContractMode()) { + case LangOptions::FPC_Off: + // Preserve any contraction performed by the front-end. (Strict performs + // splitting of the muladd instrinsic in the backend.) + Options.AllowFPOpFusion = llvm::FPOpFusion::Standard; + break; + case LangOptions::FPC_On: + Options.AllowFPOpFusion = llvm::FPOpFusion::Standard; + break; + case LangOptions::FPC_Fast: + Options.AllowFPOpFusion = llvm::FPOpFusion::Fast; + break; + } + + Options.UseInitArray = CodeGenOpts.UseInitArray; + Options.DisableIntegratedAS = CodeGenOpts.DisableIntegratedAS; + Options.CompressDebugSections = CodeGenOpts.getCompressDebugSections(); + Options.RelaxELFRelocations = CodeGenOpts.RelaxELFRelocations; + + // Set EABI version. + Options.EABIVersion = TargetOpts.EABIVersion; + + if (LangOpts.SjLjExceptions) + Options.ExceptionModel = llvm::ExceptionHandling::SjLj; + + Options.NoInfsFPMath = CodeGenOpts.NoInfsFPMath; + Options.NoNaNsFPMath = CodeGenOpts.NoNaNsFPMath; + Options.NoZerosInBSS = CodeGenOpts.NoZeroInitializedInBSS; + Options.UnsafeFPMath = CodeGenOpts.UnsafeFPMath; + Options.StackAlignmentOverride = CodeGenOpts.StackAlignment; + Options.FunctionSections = CodeGenOpts.FunctionSections; + Options.DataSections = CodeGenOpts.DataSections; + Options.UniqueSectionNames = CodeGenOpts.UniqueSectionNames; + Options.EmulatedTLS = CodeGenOpts.EmulatedTLS; + Options.DebuggerTuning = CodeGenOpts.getDebuggerTuning(); + + if (CodeGenOpts.EnableSplitDwarf) + Options.MCOptions.SplitDwarfFile = CodeGenOpts.SplitDwarfFile; + Options.MCOptions.MCRelaxAll = CodeGenOpts.RelaxAll; + Options.MCOptions.MCSaveTempLabels = CodeGenOpts.SaveTempLabels; + Options.MCOptions.MCUseDwarfDirectory = !CodeGenOpts.NoDwarfDirectoryAsm; + Options.MCOptions.MCNoExecStack = CodeGenOpts.NoExecStack; + Options.MCOptions.MCIncrementalLinkerCompatible = + CodeGenOpts.IncrementalLinkerCompatible; + Options.MCOptions.MCPIECopyRelocations = CodeGenOpts.PIECopyRelocations; + Options.MCOptions.MCFatalWarnings = CodeGenOpts.FatalWarnings; + Options.MCOptions.AsmVerbose = CodeGenOpts.AsmVerbose; + Options.MCOptions.PreserveAsmComments = CodeGenOpts.PreserveAsmComments; + Options.MCOptions.ABIName = TargetOpts.ABI; +#ifndef noCbC + Options.HasCodeSegment = LangOpts.HasCodeSegment; + Options.GuaranteedTailCallOpt = LangOpts.HasCodeSegment; +#endif + for (const auto &Entry : HSOpts.UserEntries) + if (!Entry.IsFramework && + (Entry.Group == frontend::IncludeDirGroup::Quoted || + Entry.Group == frontend::IncludeDirGroup::Angled || + Entry.Group == frontend::IncludeDirGroup::System)) + Options.MCOptions.IASSearchPaths.push_back( + Entry.IgnoreSysRoot ? Entry.Path : HSOpts.Sysroot + Entry.Path); +} + +void EmitAssemblyHelper::CreatePasses(legacy::PassManager &MPM, + legacy::FunctionPassManager &FPM) { + // Handle disabling of all LLVM passes, where we want to preserve the + // internal module before any optimization. if (CodeGenOpts.DisableLLVMPasses) return; - unsigned OptLevel = CodeGenOpts.OptimizationLevel; - CodeGenOptions::InliningMethod Inlining = CodeGenOpts.getInlining(); + // Figure out TargetLibraryInfo. This needs to be added to MPM and FPM + // manually (and not via PMBuilder), since some passes (eg. InstrProfiling) + // are inserted before PMBuilder ones - they'd get the default-constructed + // TLI with an unknown target otherwise. + Triple TargetTriple(TheModule->getTargetTriple()); + std::unique_ptr<TargetLibraryInfoImpl> TLII( + createTLII(TargetTriple, CodeGenOpts)); + + PassManagerBuilderWrapper PMBuilder(TargetTriple, CodeGenOpts, LangOpts); - // Handle disabling of LLVM optimization, where we want to preserve the - // internal module before any optimization. - if (CodeGenOpts.DisableLLVMOpts) { - OptLevel = 0; - Inlining = CodeGenOpts.NoInlining; + // At O0 and O1 we only run the always inliner which is more efficient. At + // higher optimization levels we run the normal inliner. + if (CodeGenOpts.OptimizationLevel <= 1) { + bool InsertLifetimeIntrinsics = (CodeGenOpts.OptimizationLevel != 0 && + !CodeGenOpts.DisableLifetimeMarkers); + PMBuilder.Inliner = createAlwaysInlinerLegacyPass(InsertLifetimeIntrinsics); + } else { + // We do not want to inline hot callsites for SamplePGO module-summary build + // because profile annotation will happen again in ThinLTO backend, and we + // want the IR of the hot path to match the profile. + PMBuilder.Inliner = createFunctionInliningPass( + CodeGenOpts.OptimizationLevel, CodeGenOpts.OptimizeSize, + (!CodeGenOpts.SampleProfileFile.empty() && + CodeGenOpts.EmitSummaryIndex)); } - PassManagerBuilderWrapper PMBuilder(CodeGenOpts, LangOpts); - - // Figure out TargetLibraryInfo. - Triple TargetTriple(TheModule->getTargetTriple()); - PMBuilder.LibraryInfo = createTLII(TargetTriple, CodeGenOpts); - - switch (Inlining) { - case CodeGenOptions::NoInlining: - break; - case CodeGenOptions::NormalInlining: { - PMBuilder.Inliner = - createFunctionInliningPass(OptLevel, CodeGenOpts.OptimizeSize); - break; - } - case CodeGenOptions::OnlyAlwaysInlining: - // Respect always_inline. - if (OptLevel == 0) - // Do not insert lifetime intrinsics at -O0. - PMBuilder.Inliner = createAlwaysInlinerPass(false); - else - PMBuilder.Inliner = createAlwaysInlinerPass(); - break; - } - - PMBuilder.OptLevel = OptLevel; + PMBuilder.OptLevel = CodeGenOpts.OptimizationLevel; PMBuilder.SizeLevel = CodeGenOpts.OptimizeSize; - PMBuilder.BBVectorize = CodeGenOpts.VectorizeBB; PMBuilder.SLPVectorize = CodeGenOpts.VectorizeSLP; PMBuilder.LoopVectorize = CodeGenOpts.VectorizeLoop; - PMBuilder.DisableUnitAtATime = !CodeGenOpts.UnitAtATime; PMBuilder.DisableUnrollLoops = !CodeGenOpts.UnrollLoops; PMBuilder.MergeFunctions = CodeGenOpts.MergeFunctions; + PMBuilder.PrepareForThinLTO = CodeGenOpts.EmitSummaryIndex; PMBuilder.PrepareForLTO = CodeGenOpts.PrepareForLTO; PMBuilder.RerollLoops = CodeGenOpts.RerollLoops; - legacy::PassManager *MPM = getPerModulePasses(); + MPM.add(new TargetLibraryInfoWrapperPass(*TLII)); + + if (TM) + TM->adjustPassManager(PMBuilder); - // If we are performing a ThinLTO importing compile, invoke the LTO - // pipeline and pass down the in-memory function index. - if (FunctionIndex) { - PMBuilder.FunctionIndex = FunctionIndex; - PMBuilder.populateLTOPassManager(*MPM); - return; - } - - PMBuilder.addExtension(PassManagerBuilder::EP_EarlyAsPossible, - addAddDiscriminatorsPass); + if (CodeGenOpts.DebugInfoForProfiling || + !CodeGenOpts.SampleProfileFile.empty()) + PMBuilder.addExtension(PassManagerBuilder::EP_EarlyAsPossible, + addAddDiscriminatorsPass); // In ObjC ARC mode, add the main ARC optimization passes. if (LangOpts.ObjCAutoRefCount) { @@ -401,15 +576,24 @@ addDataFlowSanitizerPass); } + if (LangOpts.CoroutinesTS) + addCoroutinePassesToExtensionPoints(PMBuilder); + + if (LangOpts.Sanitize.hasOneOf(SanitizerKind::Efficiency)) { + PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast, + addEfficiencySanitizerPass); + PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0, + addEfficiencySanitizerPass); + } + // Set up the per-function pass manager. - legacy::FunctionPassManager *FPM = getPerFunctionPasses(); + FPM.add(new TargetLibraryInfoWrapperPass(*TLII)); if (CodeGenOpts.VerifyModule) - FPM->add(createVerifierPass()); - PMBuilder.populateFunctionPassManager(*FPM); + FPM.add(createVerifierPass()); // Set up the per-module pass manager. if (!CodeGenOpts.RewriteMapFiles.empty()) - addSymbolRewriterPass(CodeGenOpts, MPM); + addSymbolRewriterPass(CodeGenOpts, &MPM); if (!CodeGenOpts.DisableGCov && (CodeGenOpts.EmitGcovArcs || CodeGenOpts.EmitGcovNotes)) { @@ -424,46 +608,35 @@ Options.FunctionNamesInData = !CodeGenOpts.CoverageNoFunctionNamesInData; Options.ExitBlockBeforeBody = CodeGenOpts.CoverageExitBlockBeforeBody; - MPM->add(createGCOVProfilerPass(Options)); - if (CodeGenOpts.getDebugInfo() == CodeGenOptions::NoDebugInfo) - MPM->add(createStripSymbolsPass(true)); + MPM.add(createGCOVProfilerPass(Options)); + if (CodeGenOpts.getDebugInfo() == codegenoptions::NoDebugInfo) + MPM.add(createStripSymbolsPass(true)); } - if (CodeGenOpts.ProfileInstrGenerate) { + if (CodeGenOpts.hasProfileClangInstr()) { InstrProfOptions Options; Options.NoRedZone = CodeGenOpts.DisableRedZone; Options.InstrProfileOutput = CodeGenOpts.InstrProfileOutput; - MPM->add(createInstrProfilingPass(Options)); + MPM.add(createInstrProfilingLegacyPass(Options)); } + if (CodeGenOpts.hasProfileIRInstr()) { + PMBuilder.EnablePGOInstrGen = true; + if (!CodeGenOpts.InstrProfileOutput.empty()) + PMBuilder.PGOInstrGen = CodeGenOpts.InstrProfileOutput; + else + PMBuilder.PGOInstrGen = DefaultProfileGenName; + } + if (CodeGenOpts.hasProfileIRUse()) + PMBuilder.PGOInstrUse = CodeGenOpts.ProfileInstrumentUsePath; if (!CodeGenOpts.SampleProfileFile.empty()) - MPM->add(createSampleProfileLoaderPass(CodeGenOpts.SampleProfileFile)); + PMBuilder.PGOSampleUse = CodeGenOpts.SampleProfileFile; - PMBuilder.populateModulePassManager(*MPM); + PMBuilder.populateFunctionPassManager(FPM); + PMBuilder.populateModulePassManager(MPM); } -TargetMachine *EmitAssemblyHelper::CreateTargetMachine(bool MustCreateTM) { - // Create the TargetMachine for generating code. - std::string Error; - std::string Triple = TheModule->getTargetTriple(); - const llvm::Target *TheTarget = TargetRegistry::lookupTarget(Triple, Error); - if (!TheTarget) { - if (MustCreateTM) - Diags.Report(diag::err_fe_unable_to_create_target) << Error; - return nullptr; - } - - unsigned CodeModel = - llvm::StringSwitch<unsigned>(CodeGenOpts.CodeModel) - .Case("small", llvm::CodeModel::Small) - .Case("kernel", llvm::CodeModel::Kernel) - .Case("medium", llvm::CodeModel::Medium) - .Case("large", llvm::CodeModel::Large) - .Case("default", llvm::CodeModel::Default) - .Default(~0u); - assert(CodeModel != ~0u && "invalid code model!"); - llvm::CodeModel::Model CM = static_cast<llvm::CodeModel::Model>(CodeModel); - +static void setCommandLineOpts(const CodeGenOptions &CodeGenOpts) { SmallVector<const char *, 16> BackendArgs; BackendArgs.push_back("clang"); // Fake program name. if (!CodeGenOpts.DebugPass.empty()) { @@ -479,149 +652,51 @@ BackendArgs.push_back(nullptr); llvm::cl::ParseCommandLineOptions(BackendArgs.size() - 1, BackendArgs.data()); - - std::string FeaturesStr = - llvm::join(TargetOpts.Features.begin(), TargetOpts.Features.end(), ","); - - // Keep this synced with the equivalent code in tools/driver/cc1as_main.cpp. - llvm::Reloc::Model RM = llvm::Reloc::Default; - if (CodeGenOpts.RelocationModel == "static") { - RM = llvm::Reloc::Static; - } else if (CodeGenOpts.RelocationModel == "pic") { - RM = llvm::Reloc::PIC_; - } else { - assert(CodeGenOpts.RelocationModel == "dynamic-no-pic" && - "Invalid PIC model!"); - RM = llvm::Reloc::DynamicNoPIC; - } - - CodeGenOpt::Level OptLevel = CodeGenOpt::Default; - switch (CodeGenOpts.OptimizationLevel) { - default: break; - case 0: OptLevel = CodeGenOpt::None; break; - case 3: OptLevel = CodeGenOpt::Aggressive; break; - } - - llvm::TargetOptions Options; - - if (!TargetOpts.Reciprocals.empty()) - Options.Reciprocals = TargetRecip(TargetOpts.Reciprocals); +} - Options.ThreadModel = - llvm::StringSwitch<llvm::ThreadModel::Model>(CodeGenOpts.ThreadModel) - .Case("posix", llvm::ThreadModel::POSIX) - .Case("single", llvm::ThreadModel::Single); - - // Set float ABI type. - assert((CodeGenOpts.FloatABI == "soft" || CodeGenOpts.FloatABI == "softfp" || - CodeGenOpts.FloatABI == "hard" || CodeGenOpts.FloatABI.empty()) && - "Invalid Floating Point ABI!"); - Options.FloatABIType = - llvm::StringSwitch<llvm::FloatABI::ABIType>(CodeGenOpts.FloatABI) - .Case("soft", llvm::FloatABI::Soft) - .Case("softfp", llvm::FloatABI::Soft) - .Case("hard", llvm::FloatABI::Hard) - .Default(llvm::FloatABI::Default); - - // Set FP fusion mode. - switch (CodeGenOpts.getFPContractMode()) { - case CodeGenOptions::FPC_Off: - Options.AllowFPOpFusion = llvm::FPOpFusion::Strict; - break; - case CodeGenOptions::FPC_On: - Options.AllowFPOpFusion = llvm::FPOpFusion::Standard; - break; - case CodeGenOptions::FPC_Fast: - Options.AllowFPOpFusion = llvm::FPOpFusion::Fast; - break; +void EmitAssemblyHelper::CreateTargetMachine(bool MustCreateTM) { + // Create the TargetMachine for generating code. + std::string Error; + std::string Triple = TheModule->getTargetTriple(); + const llvm::Target *TheTarget = TargetRegistry::lookupTarget(Triple, Error); + if (!TheTarget) { + if (MustCreateTM) + Diags.Report(diag::err_fe_unable_to_create_target) << Error; + return; } - Options.UseInitArray = CodeGenOpts.UseInitArray; - Options.DisableIntegratedAS = CodeGenOpts.DisableIntegratedAS; - Options.CompressDebugSections = CodeGenOpts.CompressDebugSections; - - // Set EABI version. - Options.EABIVersion = llvm::StringSwitch<llvm::EABI>(CodeGenOpts.EABIVersion) - .Case("4", llvm::EABI::EABI4) - .Case("5", llvm::EABI::EABI5) - .Case("gnu", llvm::EABI::GNU) - .Default(llvm::EABI::Default); + Optional<llvm::CodeModel::Model> CM = getCodeModel(CodeGenOpts); + std::string FeaturesStr = + llvm::join(TargetOpts.Features.begin(), TargetOpts.Features.end(), ","); + llvm::Reloc::Model RM = getRelocModel(CodeGenOpts); + CodeGenOpt::Level OptLevel = getCGOptLevel(CodeGenOpts); - Options.LessPreciseFPMADOption = CodeGenOpts.LessPreciseFPMAD; - Options.NoInfsFPMath = CodeGenOpts.NoInfsFPMath; - Options.NoNaNsFPMath = CodeGenOpts.NoNaNsFPMath; - Options.NoZerosInBSS = CodeGenOpts.NoZeroInitializedInBSS; - Options.UnsafeFPMath = CodeGenOpts.UnsafeFPMath; - Options.StackAlignmentOverride = CodeGenOpts.StackAlignment; - Options.PositionIndependentExecutable = LangOpts.PIELevel != 0; - Options.FunctionSections = CodeGenOpts.FunctionSections; - Options.DataSections = CodeGenOpts.DataSections; - Options.UniqueSectionNames = CodeGenOpts.UniqueSectionNames; - Options.EmulatedTLS = CodeGenOpts.EmulatedTLS; - switch (CodeGenOpts.getDebuggerTuning()) { - case CodeGenOptions::DebuggerKindGDB: - Options.DebuggerTuning = llvm::DebuggerKind::GDB; - break; - case CodeGenOptions::DebuggerKindLLDB: - Options.DebuggerTuning = llvm::DebuggerKind::LLDB; - break; - case CodeGenOptions::DebuggerKindSCE: - Options.DebuggerTuning = llvm::DebuggerKind::SCE; - break; - default: - break; - } - - Options.MCOptions.MCRelaxAll = CodeGenOpts.RelaxAll; - Options.MCOptions.MCSaveTempLabels = CodeGenOpts.SaveTempLabels; - Options.MCOptions.MCUseDwarfDirectory = !CodeGenOpts.NoDwarfDirectoryAsm; - Options.MCOptions.MCNoExecStack = CodeGenOpts.NoExecStack; - Options.MCOptions.MCIncrementalLinkerCompatible = - CodeGenOpts.IncrementalLinkerCompatible; - Options.MCOptions.MCFatalWarnings = CodeGenOpts.FatalWarnings; - Options.MCOptions.AsmVerbose = CodeGenOpts.AsmVerbose; - Options.MCOptions.ABIName = TargetOpts.ABI; -#ifndef noCbC - Options.HasCodeSegment = LangOpts.HasCodeSegment; - Options.GuaranteedTailCallOpt = LangOpts.HasCodeSegment; -#endif - - TargetMachine *TM = TheTarget->createTargetMachine(Triple, TargetOpts.CPU, - FeaturesStr, Options, - RM, CM, OptLevel); - - return TM; + llvm::TargetOptions Options; + initTargetOptions(Options, CodeGenOpts, TargetOpts, LangOpts, HSOpts); + TM.reset(TheTarget->createTargetMachine(Triple, TargetOpts.CPU, FeaturesStr, + Options, RM, CM, OptLevel)); } -bool EmitAssemblyHelper::AddEmitPasses(BackendAction Action, +bool EmitAssemblyHelper::AddEmitPasses(legacy::PassManager &CodeGenPasses, + BackendAction Action, raw_pwrite_stream &OS) { - - // Create the code generator passes. - legacy::PassManager *PM = getCodeGenPasses(); - // Add LibraryInfo. llvm::Triple TargetTriple(TheModule->getTargetTriple()); std::unique_ptr<TargetLibraryInfoImpl> TLII( createTLII(TargetTriple, CodeGenOpts)); - PM->add(new TargetLibraryInfoWrapperPass(*TLII)); + CodeGenPasses.add(new TargetLibraryInfoWrapperPass(*TLII)); // Normal mode, emit a .s or .o file by running the code generator. Note, // this also adds codegenerator level optimization passes. - TargetMachine::CodeGenFileType CGFT = TargetMachine::CGFT_AssemblyFile; - if (Action == Backend_EmitObj) - CGFT = TargetMachine::CGFT_ObjectFile; - else if (Action == Backend_EmitMCNull) - CGFT = TargetMachine::CGFT_Null; - else - assert(Action == Backend_EmitAssembly && "Invalid action!"); + TargetMachine::CodeGenFileType CGFT = getCodeGenFileType(Action); // Add ObjC ARC final-cleanup optimizations. This is done as part of the // "codegen" passes so that it isn't run multiple times when there is // inlining happening. if (CodeGenOpts.OptimizationLevel > 0) - PM->add(createObjCARCContractPass()); + CodeGenPasses.add(createObjCARCContractPass()); - if (TM->addPassesToEmitFile(*PM, OS, CGFT, + if (TM->addPassesToEmitFile(CodeGenPasses, OS, CGFT, /*DisableVerify=*/!CodeGenOpts.VerifyModule)) { Diags.Report(diag::err_fe_unable_to_interface_with_target); return false; @@ -631,58 +706,69 @@ } void EmitAssemblyHelper::EmitAssembly(BackendAction Action, - raw_pwrite_stream *OS) { + std::unique_ptr<raw_pwrite_stream> OS) { TimeRegion Region(llvm::TimePassesIsEnabled ? &CodeGenerationTime : nullptr); + setCommandLineOpts(CodeGenOpts); + bool UsesCodeGen = (Action != Backend_EmitNothing && Action != Backend_EmitBC && Action != Backend_EmitLL); - if (!TM) - TM.reset(CreateTargetMachine(UsesCodeGen)); + CreateTargetMachine(UsesCodeGen); if (UsesCodeGen && !TM) return; if (TM) TheModule->setDataLayout(TM->createDataLayout()); - // If we are performing a ThinLTO importing compile, load the function - // index into memory and pass it into CreatePasses, which will add it - // to the PassManagerBuilder and invoke LTO passes. - std::unique_ptr<FunctionInfoIndex> FunctionIndex; - if (!CodeGenOpts.ThinLTOIndexFile.empty()) { - ErrorOr<std::unique_ptr<FunctionInfoIndex>> IndexOrErr = - llvm::getFunctionIndexForFile(CodeGenOpts.ThinLTOIndexFile, - [&](const DiagnosticInfo &DI) { - TheModule->getContext().diagnose(DI); - }); - if (std::error_code EC = IndexOrErr.getError()) { - std::string Error = EC.message(); - errs() << "Error loading index file '" << CodeGenOpts.ThinLTOIndexFile - << "': " << Error << "\n"; - return; - } - FunctionIndex = std::move(IndexOrErr.get()); - assert(FunctionIndex && "Expected non-empty function index"); - } + legacy::PassManager PerModulePasses; + PerModulePasses.add( + createTargetTransformInfoWrapperPass(getTargetIRAnalysis())); + + legacy::FunctionPassManager PerFunctionPasses(TheModule); + PerFunctionPasses.add( + createTargetTransformInfoWrapperPass(getTargetIRAnalysis())); - CreatePasses(FunctionIndex.get()); + CreatePasses(PerModulePasses, PerFunctionPasses); + + legacy::PassManager CodeGenPasses; + CodeGenPasses.add( + createTargetTransformInfoWrapperPass(getTargetIRAnalysis())); + + std::unique_ptr<raw_fd_ostream> ThinLinkOS; switch (Action) { case Backend_EmitNothing: break; case Backend_EmitBC: - getPerModulePasses()->add(createBitcodeWriterPass( - *OS, CodeGenOpts.EmitLLVMUseLists, CodeGenOpts.EmitFunctionSummary)); + if (CodeGenOpts.EmitSummaryIndex) { + if (!CodeGenOpts.ThinLinkBitcodeFile.empty()) { + std::error_code EC; + ThinLinkOS.reset(new llvm::raw_fd_ostream( + CodeGenOpts.ThinLinkBitcodeFile, EC, + llvm::sys::fs::F_None)); + if (EC) { + Diags.Report(diag::err_fe_unable_to_open_output) << CodeGenOpts.ThinLinkBitcodeFile + << EC.message(); + return; + } + } + PerModulePasses.add( + createWriteThinLTOBitcodePass(*OS, ThinLinkOS.get())); + } + else + PerModulePasses.add( + createBitcodeWriterPass(*OS, CodeGenOpts.EmitLLVMUseLists)); break; case Backend_EmitLL: - getPerModulePasses()->add( + PerModulePasses.add( createPrintModulePass(*OS, "", CodeGenOpts.EmitLLVMUseLists)); break; default: - if (!AddEmitPasses(Action, *OS)) + if (!AddEmitPasses(CodeGenPasses, Action, *OS)) return; } @@ -692,46 +778,506 @@ // Run passes. For now we do all passes at once, but eventually we // would like to have the option of streaming code generation. - if (PerFunctionPasses) { + { PrettyStackTraceString CrashInfo("Per-function optimization"); - PerFunctionPasses->doInitialization(); + PerFunctionPasses.doInitialization(); for (Function &F : *TheModule) if (!F.isDeclaration()) - PerFunctionPasses->run(F); - PerFunctionPasses->doFinalization(); + PerFunctionPasses.run(F); + PerFunctionPasses.doFinalization(); + } + + { + PrettyStackTraceString CrashInfo("Per-module optimization passes"); + PerModulePasses.run(*TheModule); + } + + { + PrettyStackTraceString CrashInfo("Code generation"); + CodeGenPasses.run(*TheModule); + } +} + +static PassBuilder::OptimizationLevel mapToLevel(const CodeGenOptions &Opts) { + switch (Opts.OptimizationLevel) { + default: + llvm_unreachable("Invalid optimization level!"); + + case 1: + return PassBuilder::O1; + + case 2: + switch (Opts.OptimizeSize) { + default: + llvm_unreachable("Invalide optimization level for size!"); + + case 0: + return PassBuilder::O2; + + case 1: + return PassBuilder::Os; + + case 2: + return PassBuilder::Oz; + } + + case 3: + return PassBuilder::O3; + } +} + +/// A clean version of `EmitAssembly` that uses the new pass manager. +/// +/// Not all features are currently supported in this system, but where +/// necessary it falls back to the legacy pass manager to at least provide +/// basic functionality. +/// +/// This API is planned to have its functionality finished and then to replace +/// `EmitAssembly` at some point in the future when the default switches. +void EmitAssemblyHelper::EmitAssemblyWithNewPassManager( + BackendAction Action, std::unique_ptr<raw_pwrite_stream> OS) { + TimeRegion Region(llvm::TimePassesIsEnabled ? &CodeGenerationTime : nullptr); + setCommandLineOpts(CodeGenOpts); + + // The new pass manager always makes a target machine available to passes + // during construction. + CreateTargetMachine(/*MustCreateTM*/ true); + if (!TM) + // This will already be diagnosed, just bail. + return; + TheModule->setDataLayout(TM->createDataLayout()); + + Optional<PGOOptions> PGOOpt; + + if (CodeGenOpts.hasProfileIRInstr()) + // -fprofile-generate. + PGOOpt = PGOOptions(CodeGenOpts.InstrProfileOutput.empty() + ? DefaultProfileGenName + : CodeGenOpts.InstrProfileOutput, + "", "", true, CodeGenOpts.DebugInfoForProfiling); + else if (CodeGenOpts.hasProfileIRUse()) + // -fprofile-use. + PGOOpt = PGOOptions("", CodeGenOpts.ProfileInstrumentUsePath, "", false, + CodeGenOpts.DebugInfoForProfiling); + else if (!CodeGenOpts.SampleProfileFile.empty()) + // -fprofile-sample-use + PGOOpt = PGOOptions("", "", CodeGenOpts.SampleProfileFile, false, + CodeGenOpts.DebugInfoForProfiling); + else if (CodeGenOpts.DebugInfoForProfiling) + // -fdebug-info-for-profiling + PGOOpt = PGOOptions("", "", "", false, true); + + PassBuilder PB(TM.get(), PGOOpt); + + LoopAnalysisManager LAM; + FunctionAnalysisManager FAM; + CGSCCAnalysisManager CGAM; + ModuleAnalysisManager MAM; + + // Register the AA manager first so that our version is the one used. + FAM.registerPass([&] { return PB.buildDefaultAAPipeline(); }); + + // Register the target library analysis directly and give it a customized + // preset TLI. + Triple TargetTriple(TheModule->getTargetTriple()); + std::unique_ptr<TargetLibraryInfoImpl> TLII( + createTLII(TargetTriple, CodeGenOpts)); + FAM.registerPass([&] { return TargetLibraryAnalysis(*TLII); }); + MAM.registerPass([&] { return TargetLibraryAnalysis(*TLII); }); + + // Register all the basic analyses with the managers. + PB.registerModuleAnalyses(MAM); + PB.registerCGSCCAnalyses(CGAM); + PB.registerFunctionAnalyses(FAM); + PB.registerLoopAnalyses(LAM); + PB.crossRegisterProxies(LAM, FAM, CGAM, MAM); + + ModulePassManager MPM(CodeGenOpts.DebugPassManager); + + if (!CodeGenOpts.DisableLLVMPasses) { + bool IsThinLTO = CodeGenOpts.EmitSummaryIndex; + bool IsLTO = CodeGenOpts.PrepareForLTO; + + if (CodeGenOpts.OptimizationLevel == 0) { + // Build a minimal pipeline based on the semantics required by Clang, + // which is just that always inlining occurs. + MPM.addPass(AlwaysInlinerPass()); + if (IsThinLTO) + MPM.addPass(NameAnonGlobalPass()); + } else { + // Map our optimization levels into one of the distinct levels used to + // configure the pipeline. + PassBuilder::OptimizationLevel Level = mapToLevel(CodeGenOpts); + + if (IsThinLTO) { + MPM = PB.buildThinLTOPreLinkDefaultPipeline( + Level, CodeGenOpts.DebugPassManager); + MPM.addPass(NameAnonGlobalPass()); + } else if (IsLTO) { + MPM = PB.buildLTOPreLinkDefaultPipeline(Level, + CodeGenOpts.DebugPassManager); + } else { + MPM = PB.buildPerModuleDefaultPipeline(Level, + CodeGenOpts.DebugPassManager); + } + } } - if (PerModulePasses) { - PrettyStackTraceString CrashInfo("Per-module optimization passes"); - PerModulePasses->run(*TheModule); + // FIXME: We still use the legacy pass manager to do code generation. We + // create that pass manager here and use it as needed below. + legacy::PassManager CodeGenPasses; + bool NeedCodeGen = false; + Optional<raw_fd_ostream> ThinLinkOS; + + // Append any output we need to the pass manager. + switch (Action) { + case Backend_EmitNothing: + break; + + case Backend_EmitBC: + if (CodeGenOpts.EmitSummaryIndex) { + if (!CodeGenOpts.ThinLinkBitcodeFile.empty()) { + std::error_code EC; + ThinLinkOS.emplace(CodeGenOpts.ThinLinkBitcodeFile, EC, + llvm::sys::fs::F_None); + if (EC) { + Diags.Report(diag::err_fe_unable_to_open_output) + << CodeGenOpts.ThinLinkBitcodeFile << EC.message(); + return; + } + } + MPM.addPass( + ThinLTOBitcodeWriterPass(*OS, ThinLinkOS ? &*ThinLinkOS : nullptr)); + } else { + MPM.addPass(BitcodeWriterPass(*OS, CodeGenOpts.EmitLLVMUseLists, + CodeGenOpts.EmitSummaryIndex, + CodeGenOpts.EmitSummaryIndex)); + } + break; + + case Backend_EmitLL: + MPM.addPass(PrintModulePass(*OS, "", CodeGenOpts.EmitLLVMUseLists)); + break; + + case Backend_EmitAssembly: + case Backend_EmitMCNull: + case Backend_EmitObj: + NeedCodeGen = true; + CodeGenPasses.add( + createTargetTransformInfoWrapperPass(getTargetIRAnalysis())); + if (!AddEmitPasses(CodeGenPasses, Action, *OS)) + // FIXME: Should we handle this error differently? + return; + break; + } + + // Before executing passes, print the final values of the LLVM options. + cl::PrintOptionValues(); + + // Now that we have all of the passes ready, run them. + { + PrettyStackTraceString CrashInfo("Optimizer"); + MPM.run(*TheModule, MAM); + } + + // Now if needed, run the legacy PM for codegen. + if (NeedCodeGen) { + PrettyStackTraceString CrashInfo("Code generation"); + CodeGenPasses.run(*TheModule); + } +} + +Expected<BitcodeModule> clang::FindThinLTOModule(MemoryBufferRef MBRef) { + Expected<std::vector<BitcodeModule>> BMsOrErr = getBitcodeModuleList(MBRef); + if (!BMsOrErr) + return BMsOrErr.takeError(); + + // The bitcode file may contain multiple modules, we want the one that is + // marked as being the ThinLTO module. + for (BitcodeModule &BM : *BMsOrErr) { + Expected<BitcodeLTOInfo> LTOInfo = BM.getLTOInfo(); + if (LTOInfo && LTOInfo->IsThinLTO) + return BM; } - if (CodeGenPasses) { - PrettyStackTraceString CrashInfo("Code generation"); - CodeGenPasses->run(*TheModule); + return make_error<StringError>("Could not find module summary", + inconvertibleErrorCode()); +} + +static void runThinLTOBackend(ModuleSummaryIndex *CombinedIndex, Module *M, + const HeaderSearchOptions &HeaderOpts, + const CodeGenOptions &CGOpts, + const clang::TargetOptions &TOpts, + const LangOptions &LOpts, + std::unique_ptr<raw_pwrite_stream> OS, + std::string SampleProfile, + BackendAction Action) { + StringMap<DenseMap<GlobalValue::GUID, GlobalValueSummary *>> + ModuleToDefinedGVSummaries; + CombinedIndex->collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries); + + setCommandLineOpts(CGOpts); + + // We can simply import the values mentioned in the combined index, since + // we should only invoke this using the individual indexes written out + // via a WriteIndexesThinBackend. + FunctionImporter::ImportMapTy ImportList; + for (auto &GlobalList : *CombinedIndex) { + // Ignore entries for undefined references. + if (GlobalList.second.SummaryList.empty()) + continue; + + auto GUID = GlobalList.first; + assert(GlobalList.second.SummaryList.size() == 1 && + "Expected individual combined index to have one summary per GUID"); + auto &Summary = GlobalList.second.SummaryList[0]; + // Skip the summaries for the importing module. These are included to + // e.g. record required linkage changes. + if (Summary->modulePath() == M->getModuleIdentifier()) + continue; + // Doesn't matter what value we plug in to the map, just needs an entry + // to provoke importing by thinBackend. + ImportList[Summary->modulePath()][GUID] = 1; + } + + std::vector<std::unique_ptr<llvm::MemoryBuffer>> OwnedImports; + MapVector<llvm::StringRef, llvm::BitcodeModule> ModuleMap; + + for (auto &I : ImportList) { + ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> MBOrErr = + llvm::MemoryBuffer::getFile(I.first()); + if (!MBOrErr) { + errs() << "Error loading imported file '" << I.first() + << "': " << MBOrErr.getError().message() << "\n"; + return; + } + + Expected<BitcodeModule> BMOrErr = FindThinLTOModule(**MBOrErr); + if (!BMOrErr) { + handleAllErrors(BMOrErr.takeError(), [&](ErrorInfoBase &EIB) { + errs() << "Error loading imported file '" << I.first() + << "': " << EIB.message() << '\n'; + }); + return; + } + ModuleMap.insert({I.first(), *BMOrErr}); + + OwnedImports.push_back(std::move(*MBOrErr)); + } + auto AddStream = [&](size_t Task) { + return llvm::make_unique<lto::NativeObjectStream>(std::move(OS)); + }; + lto::Config Conf; + Conf.CPU = TOpts.CPU; + Conf.CodeModel = getCodeModel(CGOpts); + Conf.MAttrs = TOpts.Features; + Conf.RelocModel = getRelocModel(CGOpts); + Conf.CGOptLevel = getCGOptLevel(CGOpts); + initTargetOptions(Conf.Options, CGOpts, TOpts, LOpts, HeaderOpts); + Conf.SampleProfile = std::move(SampleProfile); + Conf.UseNewPM = CGOpts.ExperimentalNewPassManager; + switch (Action) { + case Backend_EmitNothing: + Conf.PreCodeGenModuleHook = [](size_t Task, const Module &Mod) { + return false; + }; + break; + case Backend_EmitLL: + Conf.PreCodeGenModuleHook = [&](size_t Task, const Module &Mod) { + M->print(*OS, nullptr, CGOpts.EmitLLVMUseLists); + return false; + }; + break; + case Backend_EmitBC: + Conf.PreCodeGenModuleHook = [&](size_t Task, const Module &Mod) { + WriteBitcodeToFile(M, *OS, CGOpts.EmitLLVMUseLists); + return false; + }; + break; + default: + Conf.CGFileType = getCodeGenFileType(Action); + break; + } + if (Error E = thinBackend( + Conf, 0, AddStream, *M, *CombinedIndex, ImportList, + ModuleToDefinedGVSummaries[M->getModuleIdentifier()], ModuleMap)) { + handleAllErrors(std::move(E), [&](ErrorInfoBase &EIB) { + errs() << "Error running ThinLTO backend: " << EIB.message() << '\n'; + }); } } void clang::EmitBackendOutput(DiagnosticsEngine &Diags, + const HeaderSearchOptions &HeaderOpts, const CodeGenOptions &CGOpts, const clang::TargetOptions &TOpts, - const LangOptions &LOpts, StringRef TDesc, - Module *M, BackendAction Action, - raw_pwrite_stream *OS) { - EmitAssemblyHelper AsmHelper(Diags, CGOpts, TOpts, LOpts, M); + const LangOptions &LOpts, + const llvm::DataLayout &TDesc, Module *M, + BackendAction Action, + std::unique_ptr<raw_pwrite_stream> OS) { + if (!CGOpts.ThinLTOIndexFile.empty()) { + // If we are performing a ThinLTO importing compile, load the function index + // into memory and pass it into runThinLTOBackend, which will run the + // function importer and invoke LTO passes. + Expected<std::unique_ptr<ModuleSummaryIndex>> IndexOrErr = + llvm::getModuleSummaryIndexForFile(CGOpts.ThinLTOIndexFile, + /*IgnoreEmptyThinLTOIndexFile*/true); + if (!IndexOrErr) { + logAllUnhandledErrors(IndexOrErr.takeError(), errs(), + "Error loading index file '" + + CGOpts.ThinLTOIndexFile + "': "); + return; + } + std::unique_ptr<ModuleSummaryIndex> CombinedIndex = std::move(*IndexOrErr); + // A null CombinedIndex means we should skip ThinLTO compilation + // (LLVM will optionally ignore empty index files, returning null instead + // of an error). + bool DoThinLTOBackend = CombinedIndex != nullptr; + if (DoThinLTOBackend) { + runThinLTOBackend(CombinedIndex.get(), M, HeaderOpts, CGOpts, TOpts, + LOpts, std::move(OS), CGOpts.SampleProfileFile, Action); + return; + } + } - AsmHelper.EmitAssembly(Action, OS); + EmitAssemblyHelper AsmHelper(Diags, HeaderOpts, CGOpts, TOpts, LOpts, M); - // If an optional clang TargetInfo description string was passed in, use it to - // verify the LLVM TargetMachine's DataLayout. - if (AsmHelper.TM && !TDesc.empty()) { + if (CGOpts.ExperimentalNewPassManager) + AsmHelper.EmitAssemblyWithNewPassManager(Action, std::move(OS)); + else + AsmHelper.EmitAssembly(Action, std::move(OS)); + + // Verify clang's TargetInfo DataLayout against the LLVM TargetMachine's + // DataLayout. + if (AsmHelper.TM) { std::string DLDesc = M->getDataLayout().getStringRepresentation(); - if (DLDesc != TDesc) { + if (DLDesc != TDesc.getStringRepresentation()) { unsigned DiagID = Diags.getCustomDiagID( DiagnosticsEngine::Error, "backend data layout '%0' does not match " "expected target description '%1'"); - Diags.Report(DiagID) << DLDesc << TDesc; + Diags.Report(DiagID) << DLDesc << TDesc.getStringRepresentation(); } } } + +static const char* getSectionNameForBitcode(const Triple &T) { + switch (T.getObjectFormat()) { + case Triple::MachO: + return "__LLVM,__bitcode"; + case Triple::COFF: + case Triple::ELF: + case Triple::Wasm: + case Triple::UnknownObjectFormat: + return ".llvmbc"; + } + llvm_unreachable("Unimplemented ObjectFormatType"); +} + +static const char* getSectionNameForCommandline(const Triple &T) { + switch (T.getObjectFormat()) { + case Triple::MachO: + return "__LLVM,__cmdline"; + case Triple::COFF: + case Triple::ELF: + case Triple::Wasm: + case Triple::UnknownObjectFormat: + return ".llvmcmd"; + } + llvm_unreachable("Unimplemented ObjectFormatType"); +} + +// With -fembed-bitcode, save a copy of the llvm IR as data in the +// __LLVM,__bitcode section. +void clang::EmbedBitcode(llvm::Module *M, const CodeGenOptions &CGOpts, + llvm::MemoryBufferRef Buf) { + if (CGOpts.getEmbedBitcode() == CodeGenOptions::Embed_Off) + return; + + // Save llvm.compiler.used and remote it. + SmallVector<Constant*, 2> UsedArray; + SmallSet<GlobalValue*, 4> UsedGlobals; + Type *UsedElementType = Type::getInt8Ty(M->getContext())->getPointerTo(0); + GlobalVariable *Used = collectUsedGlobalVariables(*M, UsedGlobals, true); + for (auto *GV : UsedGlobals) { + if (GV->getName() != "llvm.embedded.module" && + GV->getName() != "llvm.cmdline") + UsedArray.push_back( + ConstantExpr::getPointerBitCastOrAddrSpaceCast(GV, UsedElementType)); + } + if (Used) + Used->eraseFromParent(); + + // Embed the bitcode for the llvm module. + std::string Data; + ArrayRef<uint8_t> ModuleData; + Triple T(M->getTargetTriple()); + // Create a constant that contains the bitcode. + // In case of embedding a marker, ignore the input Buf and use the empty + // ArrayRef. It is also legal to create a bitcode marker even Buf is empty. + if (CGOpts.getEmbedBitcode() != CodeGenOptions::Embed_Marker) { + if (!isBitcode((const unsigned char *)Buf.getBufferStart(), + (const unsigned char *)Buf.getBufferEnd())) { + // If the input is LLVM Assembly, bitcode is produced by serializing + // the module. Use-lists order need to be perserved in this case. + llvm::raw_string_ostream OS(Data); + llvm::WriteBitcodeToFile(M, OS, /* ShouldPreserveUseListOrder */ true); + ModuleData = + ArrayRef<uint8_t>((const uint8_t *)OS.str().data(), OS.str().size()); + } else + // If the input is LLVM bitcode, write the input byte stream directly. + ModuleData = ArrayRef<uint8_t>((const uint8_t *)Buf.getBufferStart(), + Buf.getBufferSize()); + } + llvm::Constant *ModuleConstant = + llvm::ConstantDataArray::get(M->getContext(), ModuleData); + llvm::GlobalVariable *GV = new llvm::GlobalVariable( + *M, ModuleConstant->getType(), true, llvm::GlobalValue::PrivateLinkage, + ModuleConstant); + GV->setSection(getSectionNameForBitcode(T)); + UsedArray.push_back( + ConstantExpr::getPointerBitCastOrAddrSpaceCast(GV, UsedElementType)); + if (llvm::GlobalVariable *Old = + M->getGlobalVariable("llvm.embedded.module", true)) { + assert(Old->hasOneUse() && + "llvm.embedded.module can only be used once in llvm.compiler.used"); + GV->takeName(Old); + Old->eraseFromParent(); + } else { + GV->setName("llvm.embedded.module"); + } + + // Skip if only bitcode needs to be embedded. + if (CGOpts.getEmbedBitcode() != CodeGenOptions::Embed_Bitcode) { + // Embed command-line options. + ArrayRef<uint8_t> CmdData(const_cast<uint8_t *>(CGOpts.CmdArgs.data()), + CGOpts.CmdArgs.size()); + llvm::Constant *CmdConstant = + llvm::ConstantDataArray::get(M->getContext(), CmdData); + GV = new llvm::GlobalVariable(*M, CmdConstant->getType(), true, + llvm::GlobalValue::PrivateLinkage, + CmdConstant); + GV->setSection(getSectionNameForCommandline(T)); + UsedArray.push_back( + ConstantExpr::getPointerBitCastOrAddrSpaceCast(GV, UsedElementType)); + if (llvm::GlobalVariable *Old = + M->getGlobalVariable("llvm.cmdline", true)) { + assert(Old->hasOneUse() && + "llvm.cmdline can only be used once in llvm.compiler.used"); + GV->takeName(Old); + Old->eraseFromParent(); + } else { + GV->setName("llvm.cmdline"); + } + } + + if (UsedArray.empty()) + return; + + // Recreate llvm.compiler.used. + ArrayType *ATy = ArrayType::get(UsedElementType, UsedArray.size()); + auto *NewUsed = new GlobalVariable( + *M, ATy, false, llvm::GlobalValue::AppendingLinkage, + llvm::ConstantArray::get(ATy, UsedArray), "llvm.compiler.used"); + NewUsed->setSection("llvm.metadata"); +}
--- a/tools/clang/lib/CodeGen/CGCall.cpp Wed Dec 06 14:37:17 2017 +0900 +++ b/tools/clang/lib/CodeGen/CGCall.cpp Tue Dec 12 19:42:58 2017 +0900 @@ -14,6 +14,7 @@ #include "CGCall.h" #include "ABIInfo.h" +#include "CGBlocks.h" #include "CGCXXABI.h" #include "CGCleanup.h" #include "CodeGenFunction.h" @@ -25,9 +26,12 @@ #include "clang/Basic/TargetBuiltins.h" #include "clang/Basic/TargetInfo.h" #include "clang/CodeGen/CGFunctionInfo.h" +#include "clang/CodeGen/SwiftCallingConv.h" #include "clang/Frontend/CodeGenOptions.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/Attributes.h" +#include "llvm/IR/CallingConv.h" #include "llvm/IR/CallSite.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/InlineAsm.h" @@ -39,13 +43,14 @@ /***/ -static unsigned ClangCallConvToLLVMCallConv(CallingConv CC) { +unsigned CodeGenTypes::ClangCallConvToLLVMCallConv(CallingConv CC) { switch (CC) { default: return llvm::CallingConv::C; case CC_X86StdCall: return llvm::CallingConv::X86_StdCall; case CC_X86FastCall: return llvm::CallingConv::X86_FastCall; + case CC_X86RegCall: return llvm::CallingConv::X86_RegCall; case CC_X86ThisCall: return llvm::CallingConv::X86_ThisCall; - case CC_X86_64Win64: return llvm::CallingConv::X86_64_Win64; + case CC_Win64: return llvm::CallingConv::Win64; case CC_X86_64SysV: return llvm::CallingConv::X86_64_SysV; case CC_AAPCS: return llvm::CallingConv::ARM_AAPCS; case CC_AAPCS_VFP: return llvm::CallingConv::ARM_AAPCS_VFP; @@ -55,7 +60,10 @@ // TODO: Add support for __vectorcall to LLVM. case CC_X86VectorCall: return llvm::CallingConv::X86_VectorCall; case CC_SpirFunction: return llvm::CallingConv::SPIR_FUNC; - case CC_SpirKernel: return llvm::CallingConv::SPIR_KERNEL; + case CC_OpenCLKernel: return CGM.getTargetCodeGenInfo().getOpenCLKernelCallingConv(); + case CC_PreserveMost: return llvm::CallingConv::PreserveMost; + case CC_PreserveAll: return llvm::CallingConv::PreserveAll; + case CC_Swift: return llvm::CallingConv::Swift; } } @@ -90,32 +98,67 @@ return arrangeLLVMFunctionInfo(FTNP->getReturnType().getUnqualifiedType(), /*instanceMethod=*/false, /*chainCall=*/false, None, - FTNP->getExtInfo(), RequiredArgs(0)); + FTNP->getExtInfo(), {}, RequiredArgs(0)); } -/// Adds the formal paramaters in FPT to the given prefix. If any parameter in +static void addExtParameterInfosForCall( + llvm::SmallVectorImpl<FunctionProtoType::ExtParameterInfo> ¶mInfos, + const FunctionProtoType *proto, + unsigned prefixArgs, + unsigned totalArgs) { + assert(proto->hasExtParameterInfos()); + assert(paramInfos.size() <= prefixArgs); + assert(proto->getNumParams() + prefixArgs <= totalArgs); + + paramInfos.reserve(totalArgs); + + // Add default infos for any prefix args that don't already have infos. + paramInfos.resize(prefixArgs); + + // Add infos for the prototype. + for (const auto &ParamInfo : proto->getExtParameterInfos()) { + paramInfos.push_back(ParamInfo); + // pass_object_size params have no parameter info. + if (ParamInfo.hasPassObjectSize()) + paramInfos.emplace_back(); + } + + assert(paramInfos.size() <= totalArgs && + "Did we forget to insert pass_object_size args?"); + // Add default infos for the variadic and/or suffix arguments. + paramInfos.resize(totalArgs); +} + +/// Adds the formal parameters in FPT to the given prefix. If any parameter in /// FPT has pass_object_size attrs, then we'll add parameters for those, too. static void appendParameterTypes(const CodeGenTypes &CGT, SmallVectorImpl<CanQualType> &prefix, - const CanQual<FunctionProtoType> &FPT, - const FunctionDecl *FD) { - // Fast path: unknown target. - if (FD == nullptr) { + SmallVectorImpl<FunctionProtoType::ExtParameterInfo> ¶mInfos, + CanQual<FunctionProtoType> FPT) { + // Fast path: don't touch param info if we don't need to. + if (!FPT->hasExtParameterInfos()) { + assert(paramInfos.empty() && + "We have paramInfos, but the prototype doesn't?"); prefix.append(FPT->param_type_begin(), FPT->param_type_end()); return; } - // In the vast majority cases, we'll have precisely FPT->getNumParams() + unsigned PrefixSize = prefix.size(); + // In the vast majority of cases, we'll have precisely FPT->getNumParams() // parameters; the only thing that can change this is the presence of // pass_object_size. So, we preallocate for the common case. prefix.reserve(prefix.size() + FPT->getNumParams()); - assert(FD->getNumParams() == FPT->getNumParams()); + auto ExtInfos = FPT->getExtParameterInfos(); + assert(ExtInfos.size() == FPT->getNumParams()); for (unsigned I = 0, E = FPT->getNumParams(); I != E; ++I) { prefix.push_back(FPT->getParamType(I)); - if (FD->getParamDecl(I)->hasAttr<PassObjectSizeAttr>()) + if (ExtInfos[I].hasPassObjectSize()) prefix.push_back(CGT.getContext().getSizeType()); } + + addExtParameterInfosForCall(paramInfos, FPT.getTypePtr(), PrefixSize, + prefix.size()); } /// Arrange the LLVM function layout for a value of the given function @@ -125,13 +168,17 @@ SmallVectorImpl<CanQualType> &prefix, CanQual<FunctionProtoType> FTP, const FunctionDecl *FD) { - RequiredArgs required = RequiredArgs::forPrototypePlus(FTP, prefix.size()); + SmallVector<FunctionProtoType::ExtParameterInfo, 16> paramInfos; + RequiredArgs Required = + RequiredArgs::forPrototypePlus(FTP, prefix.size(), FD); // FIXME: Kill copy. - appendParameterTypes(CGT, prefix, FTP, FD); + appendParameterTypes(CGT, prefix, paramInfos, FTP); CanQualType resultType = FTP->getReturnType().getUnqualifiedType(); + return CGT.arrangeLLVMFunctionInfo(resultType, instanceMethod, /*chainCall=*/false, prefix, - FTP->getExtInfo(), required); + FTP->getExtInfo(), paramInfos, + Required); } /// Arrange the argument and result information for a value of the @@ -152,6 +199,9 @@ if (D->hasAttr<FastCallAttr>()) return CC_X86FastCall; + if (D->hasAttr<RegCallAttr>()) + return CC_X86RegCall; + if (D->hasAttr<ThisCallAttr>()) return CC_X86ThisCall; @@ -168,11 +218,17 @@ return CC_IntelOclBicc; if (D->hasAttr<MSABIAttr>()) - return IsWindows ? CC_C : CC_X86_64Win64; + return IsWindows ? CC_C : CC_Win64; if (D->hasAttr<SysVABIAttr>()) return IsWindows ? CC_X86_64SysV : CC_C; + if (D->hasAttr<PreserveMostAttr>()) + return CC_PreserveMost; + + if (D->hasAttr<PreserveAllAttr>()) + return CC_PreserveAll; + return CC_C; } @@ -219,16 +275,33 @@ return arrangeFreeFunctionType(prototype, MD); } +bool CodeGenTypes::inheritingCtorHasParams( + const InheritedConstructor &Inherited, CXXCtorType Type) { + // Parameters are unnecessary if we're constructing a base class subobject + // and the inherited constructor lives in a virtual base. + return Type == Ctor_Complete || + !Inherited.getShadowDecl()->constructsVirtualBase() || + !Target.getCXXABI().hasConstructorVariants(); + } + const CGFunctionInfo & CodeGenTypes::arrangeCXXStructorDeclaration(const CXXMethodDecl *MD, StructorType Type) { SmallVector<CanQualType, 16> argTypes; + SmallVector<FunctionProtoType::ExtParameterInfo, 16> paramInfos; argTypes.push_back(GetThisType(Context, MD->getParent())); + bool PassParams = true; + GlobalDecl GD; if (auto *CD = dyn_cast<CXXConstructorDecl>(MD)) { GD = GlobalDecl(CD, toCXXCtorType(Type)); + + // A base class inheriting constructor doesn't get forwarded arguments + // needed to construct a virtual base (or base class thereof). + if (auto Inherited = CD->getInheritedConstructor()) + PassParams = inheritingCtorHasParams(Inherited, toCXXCtorType(Type)); } else { auto *DD = dyn_cast<CXXDestructorDecl>(MD); GD = GlobalDecl(DD, toCXXDtorType(Type)); @@ -237,12 +310,24 @@ CanQual<FunctionProtoType> FTP = GetFormalType(MD); // Add the formal parameters. - appendParameterTypes(*this, argTypes, FTP, MD); - - TheCXXABI.buildStructorSignature(MD, Type, argTypes); + if (PassParams) + appendParameterTypes(*this, argTypes, paramInfos, FTP); + + CGCXXABI::AddedStructorArgs AddedArgs = + TheCXXABI.buildStructorSignature(MD, Type, argTypes); + if (!paramInfos.empty()) { + // Note: prefix implies after the first param. + if (AddedArgs.Prefix) + paramInfos.insert(paramInfos.begin() + 1, AddedArgs.Prefix, + FunctionProtoType::ExtParameterInfo{}); + if (AddedArgs.Suffix) + paramInfos.append(AddedArgs.Suffix, + FunctionProtoType::ExtParameterInfo{}); + } RequiredArgs required = - (MD->isVariadic() ? RequiredArgs(argTypes.size()) : RequiredArgs::All); + (PassParams && MD->isVariadic() ? RequiredArgs(argTypes.size()) + : RequiredArgs::All); FunctionType::ExtInfo extInfo = FTP->getExtInfo(); CanQualType resultType = TheCXXABI.HasThisReturn(GD) @@ -252,22 +337,61 @@ : Context.VoidTy; return arrangeLLVMFunctionInfo(resultType, /*instanceMethod=*/true, /*chainCall=*/false, argTypes, extInfo, - required); + paramInfos, required); +} + +static SmallVector<CanQualType, 16> +getArgTypesForCall(ASTContext &ctx, const CallArgList &args) { + SmallVector<CanQualType, 16> argTypes; + for (auto &arg : args) + argTypes.push_back(ctx.getCanonicalParamType(arg.Ty)); + return argTypes; +} + +static SmallVector<CanQualType, 16> +getArgTypesForDeclaration(ASTContext &ctx, const FunctionArgList &args) { + SmallVector<CanQualType, 16> argTypes; + for (auto &arg : args) + argTypes.push_back(ctx.getCanonicalParamType(arg->getType())); + return argTypes; +} + +static llvm::SmallVector<FunctionProtoType::ExtParameterInfo, 16> +getExtParameterInfosForCall(const FunctionProtoType *proto, + unsigned prefixArgs, unsigned totalArgs) { + llvm::SmallVector<FunctionProtoType::ExtParameterInfo, 16> result; + if (proto->hasExtParameterInfos()) { + addExtParameterInfosForCall(result, proto, prefixArgs, totalArgs); + } + return result; } /// Arrange a call to a C++ method, passing the given arguments. +/// +/// ExtraPrefixArgs is the number of ABI-specific args passed after the `this` +/// parameter. +/// ExtraSuffixArgs is the number of ABI-specific args passed at the end of +/// args. +/// PassProtoArgs indicates whether `args` has args for the parameters in the +/// given CXXConstructorDecl. const CGFunctionInfo & CodeGenTypes::arrangeCXXConstructorCall(const CallArgList &args, const CXXConstructorDecl *D, CXXCtorType CtorKind, - unsigned ExtraArgs) { + unsigned ExtraPrefixArgs, + unsigned ExtraSuffixArgs, + bool PassProtoArgs) { // FIXME: Kill copy. SmallVector<CanQualType, 16> ArgTypes; for (const auto &Arg : args) ArgTypes.push_back(Context.getCanonicalParamType(Arg.Ty)); + // +1 for implicit this, which should always be args[0]. + unsigned TotalPrefixArgs = 1 + ExtraPrefixArgs; + CanQual<FunctionProtoType> FPT = GetFormalType(D); - RequiredArgs Required = RequiredArgs::forPrototypePlus(FPT, 1 + ExtraArgs); + RequiredArgs Required = + RequiredArgs::forPrototypePlus(FPT, TotalPrefixArgs + ExtraSuffixArgs, D); GlobalDecl GD(D, CtorKind); CanQualType ResultType = TheCXXABI.HasThisReturn(GD) ? ArgTypes.front() @@ -276,9 +400,17 @@ : Context.VoidTy; FunctionType::ExtInfo Info = FPT->getExtInfo(); + llvm::SmallVector<FunctionProtoType::ExtParameterInfo, 16> ParamInfos; + // If the prototype args are elided, we should only have ABI-specific args, + // which never have param info. + if (PassProtoArgs && FPT->hasExtParameterInfos()) { + // ABI-specific suffix arguments are treated the same as variadic arguments. + addExtParameterInfosForCall(ParamInfos, FPT.getTypePtr(), TotalPrefixArgs, + ArgTypes.size()); + } return arrangeLLVMFunctionInfo(ResultType, /*instanceMethod=*/true, /*chainCall=*/false, ArgTypes, Info, - Required); + ParamInfos, Required); } /// Arrange the argument and result information for the declaration or @@ -295,15 +427,13 @@ // When declaring a function without a prototype, always use a // non-variadic type. - if (isa<FunctionNoProtoType>(FTy)) { - CanQual<FunctionNoProtoType> noProto = FTy.getAs<FunctionNoProtoType>(); + if (CanQual<FunctionNoProtoType> noProto = FTy.getAs<FunctionNoProtoType>()) { return arrangeLLVMFunctionInfo( noProto->getReturnType(), /*instanceMethod=*/false, - /*chainCall=*/false, None, noProto->getExtInfo(), RequiredArgs::All); + /*chainCall=*/false, None, noProto->getExtInfo(), {},RequiredArgs::All); } - assert(isa<FunctionProtoType>(FTy)); - return arrangeFreeFunctionType(FTy.getAs<FunctionProtoType>(), FD); + return arrangeFreeFunctionType(FTy.castAs<FunctionProtoType>(), FD); } /// Arrange the argument and result information for the declaration or @@ -325,11 +455,15 @@ CodeGenTypes::arrangeObjCMessageSendSignature(const ObjCMethodDecl *MD, QualType receiverType) { SmallVector<CanQualType, 16> argTys; + SmallVector<FunctionProtoType::ExtParameterInfo, 4> extParamInfos(2); argTys.push_back(Context.getCanonicalParamType(receiverType)); argTys.push_back(Context.getCanonicalParamType(Context.getObjCSelType())); // FIXME: Kill copy? - for (const auto *I : MD->params()) { + for (const auto *I : MD->parameters()) { argTys.push_back(Context.getCanonicalParamType(I->getType())); + auto extParamInfo = FunctionProtoType::ExtParameterInfo().withIsNoEscape( + I->hasAttr<NoEscapeAttr>()); + extParamInfos.push_back(extParamInfo); } FunctionType::ExtInfo einfo; @@ -345,7 +479,18 @@ return arrangeLLVMFunctionInfo( GetReturnType(MD->getReturnType()), /*instanceMethod=*/false, - /*chainCall=*/false, argTys, einfo, required); + /*chainCall=*/false, argTys, einfo, extParamInfos, required); +} + +const CGFunctionInfo & +CodeGenTypes::arrangeUnprototypedObjCMessageSend(QualType returnType, + const CallArgList &args) { + auto argTypes = getArgTypesForCall(Context, args); + FunctionType::ExtInfo einfo; + + return arrangeLLVMFunctionInfo( + GetReturnType(returnType), /*instanceMethod=*/false, + /*chainCall=*/false, argTypes, einfo, {}, RequiredArgs::All); } const CGFunctionInfo & @@ -374,7 +519,7 @@ CanQualType ArgTys[] = { GetThisType(Context, MD->getParent()) }; return arrangeLLVMFunctionInfo(Context.VoidTy, /*instanceMethod=*/false, /*chainCall=*/false, ArgTys, - FTP->getExtInfo(), RequiredArgs(1)); + FTP->getExtInfo(), {}, RequiredArgs(1)); } const CGFunctionInfo & @@ -394,7 +539,8 @@ /*IsVariadic=*/false, /*IsCXXMethod=*/true); return arrangeLLVMFunctionInfo(Context.VoidTy, /*instanceMethod=*/true, /*chainCall=*/false, ArgTys, - FunctionType::ExtInfo(CC), RequiredArgs::All); + FunctionType::ExtInfo(CC), {}, + RequiredArgs::All); } /// Arrange a call as unto a free function, except possibly with an @@ -408,6 +554,8 @@ bool chainCall) { assert(args.size() >= numExtraRequiredArgs); + llvm::SmallVector<FunctionProtoType::ExtParameterInfo, 16> paramInfos; + // In most cases, there are no optional arguments. RequiredArgs required = RequiredArgs::All; @@ -417,6 +565,10 @@ if (proto->isVariadic()) required = RequiredArgs(proto->getNumParams() + numExtraRequiredArgs); + if (proto->hasExtParameterInfos()) + addExtParameterInfosForCall(paramInfos, proto, numExtraRequiredArgs, + args.size()); + // If we don't have a prototype at all, but we're supposed to // explicitly use the variadic convention for unprototyped calls, // treat all of the arguments as required but preserve the nominal @@ -433,7 +585,8 @@ argTypes.push_back(CGT.getContext().getCanonicalParamType(arg.Ty)); return CGT.arrangeLLVMFunctionInfo(GetReturnType(fnType->getReturnType()), /*instanceMethod=*/false, chainCall, - argTypes, fnType->getExtInfo(), required); + argTypes, fnType->getExtInfo(), paramInfos, + required); } /// Figure out the rules for calling a function with the given formal @@ -448,7 +601,7 @@ chainCall ? 1 : 0, chainCall); } -/// A block function call is essentially a free-function call with an +/// A block function is essentially a free function with an /// extra implicit argument. const CGFunctionInfo & CodeGenTypes::arrangeBlockFunctionCall(const CallArgList &args, @@ -458,54 +611,110 @@ } const CGFunctionInfo & -CodeGenTypes::arrangeFreeFunctionCall(QualType resultType, - const CallArgList &args, - FunctionType::ExtInfo info, - RequiredArgs required) { +CodeGenTypes::arrangeBlockFunctionDeclaration(const FunctionProtoType *proto, + const FunctionArgList ¶ms) { + auto paramInfos = getExtParameterInfosForCall(proto, 1, params.size()); + auto argTypes = getArgTypesForDeclaration(Context, params); + + return arrangeLLVMFunctionInfo( + GetReturnType(proto->getReturnType()), + /*instanceMethod*/ false, /*chainCall*/ false, argTypes, + proto->getExtInfo(), paramInfos, + RequiredArgs::forPrototypePlus(proto, 1, nullptr)); +} + +const CGFunctionInfo & +CodeGenTypes::arrangeBuiltinFunctionCall(QualType resultType, + const CallArgList &args) { // FIXME: Kill copy. SmallVector<CanQualType, 16> argTypes; for (const auto &Arg : args) argTypes.push_back(Context.getCanonicalParamType(Arg.Ty)); return arrangeLLVMFunctionInfo( GetReturnType(resultType), /*instanceMethod=*/false, - /*chainCall=*/false, argTypes, info, required); + /*chainCall=*/false, argTypes, FunctionType::ExtInfo(), + /*paramInfos=*/ {}, RequiredArgs::All); +} + +const CGFunctionInfo & +CodeGenTypes::arrangeBuiltinFunctionDeclaration(QualType resultType, + const FunctionArgList &args) { + auto argTypes = getArgTypesForDeclaration(Context, args); + + return arrangeLLVMFunctionInfo( + GetReturnType(resultType), /*instanceMethod=*/false, /*chainCall=*/false, + argTypes, FunctionType::ExtInfo(), {}, RequiredArgs::All); +} + +const CGFunctionInfo & +CodeGenTypes::arrangeBuiltinFunctionDeclaration(CanQualType resultType, + ArrayRef<CanQualType> argTypes) { + return arrangeLLVMFunctionInfo( + resultType, /*instanceMethod=*/false, /*chainCall=*/false, + argTypes, FunctionType::ExtInfo(), {}, RequiredArgs::All); } /// Arrange a call to a C++ method, passing the given arguments. +/// +/// numPrefixArgs is the number of ABI-specific prefix arguments we have. It +/// does not count `this`. const CGFunctionInfo & CodeGenTypes::arrangeCXXMethodCall(const CallArgList &args, - const FunctionProtoType *FPT, - RequiredArgs required) { + const FunctionProtoType *proto, + RequiredArgs required, + unsigned numPrefixArgs) { + assert(numPrefixArgs + 1 <= args.size() && + "Emitting a call with less args than the required prefix?"); + // Add one to account for `this`. It's a bit awkward here, but we don't count + // `this` in similar places elsewhere. + auto paramInfos = + getExtParameterInfosForCall(proto, numPrefixArgs + 1, args.size()); + // FIXME: Kill copy. - SmallVector<CanQualType, 16> argTypes; - for (const auto &Arg : args) - argTypes.push_back(Context.getCanonicalParamType(Arg.Ty)); - - FunctionType::ExtInfo info = FPT->getExtInfo(); + auto argTypes = getArgTypesForCall(Context, args); + + FunctionType::ExtInfo info = proto->getExtInfo(); return arrangeLLVMFunctionInfo( - GetReturnType(FPT->getReturnType()), /*instanceMethod=*/true, - /*chainCall=*/false, argTypes, info, required); -} - -const CGFunctionInfo &CodeGenTypes::arrangeFreeFunctionDeclaration( - QualType resultType, const FunctionArgList &args, - const FunctionType::ExtInfo &info, bool isVariadic) { - // FIXME: Kill copy. - SmallVector<CanQualType, 16> argTypes; - for (auto Arg : args) - argTypes.push_back(Context.getCanonicalParamType(Arg->getType())); - - RequiredArgs required = - (isVariadic ? RequiredArgs(args.size()) : RequiredArgs::All); - return arrangeLLVMFunctionInfo( - GetReturnType(resultType), /*instanceMethod=*/false, - /*chainCall=*/false, argTypes, info, required); + GetReturnType(proto->getReturnType()), /*instanceMethod=*/true, + /*chainCall=*/false, argTypes, info, paramInfos, required); } const CGFunctionInfo &CodeGenTypes::arrangeNullaryFunction() { return arrangeLLVMFunctionInfo( getContext().VoidTy, /*instanceMethod=*/false, /*chainCall=*/false, - None, FunctionType::ExtInfo(), RequiredArgs::All); + None, FunctionType::ExtInfo(), {}, RequiredArgs::All); +} + +const CGFunctionInfo & +CodeGenTypes::arrangeCall(const CGFunctionInfo &signature, + const CallArgList &args) { + assert(signature.arg_size() <= args.size()); + if (signature.arg_size() == args.size()) + return signature; + + SmallVector<FunctionProtoType::ExtParameterInfo, 16> paramInfos; + auto sigParamInfos = signature.getExtParameterInfos(); + if (!sigParamInfos.empty()) { + paramInfos.append(sigParamInfos.begin(), sigParamInfos.end()); + paramInfos.resize(args.size()); + } + + auto argTypes = getArgTypesForCall(Context, args); + + assert(signature.getRequiredArgs().allowsOptionalArgs()); + return arrangeLLVMFunctionInfo(signature.getReturnType(), + signature.isInstanceMethod(), + signature.isChainCall(), + argTypes, + signature.getExtInfo(), + paramInfos, + signature.getRequiredArgs()); +} + +namespace clang { +namespace CodeGen { +void computeSPIRKernelABIInfo(CodeGenModule &CGM, CGFunctionInfo &FI); +} } /// Arrange the argument and result information for an abstract value @@ -517,22 +726,23 @@ bool chainCall, ArrayRef<CanQualType> argTypes, FunctionType::ExtInfo info, + ArrayRef<FunctionProtoType::ExtParameterInfo> paramInfos, RequiredArgs required) { assert(std::all_of(argTypes.begin(), argTypes.end(), - std::mem_fun_ref(&CanQualType::isCanonicalAsParam))); - - unsigned CC = ClangCallConvToLLVMCallConv(info.getCC()); + [](CanQualType T) { return T.isCanonicalAsParam(); })); // Lookup or create unique function info. llvm::FoldingSetNodeID ID; - CGFunctionInfo::Profile(ID, instanceMethod, chainCall, info, required, - resultType, argTypes); + CGFunctionInfo::Profile(ID, instanceMethod, chainCall, info, paramInfos, + required, resultType, argTypes); void *insertPos = nullptr; CGFunctionInfo *FI = FunctionInfos.FindNodeOrInsertPos(ID, insertPos); if (FI) return *FI; + unsigned CC = ClangCallConvToLLVMCallConv(info.getCC()); + #ifndef noCbC // if the function is a code segment , set fastcall calling convention. if(resultType.getTypePtr()->is__CodeType()){ @@ -542,15 +752,23 @@ // Construct the function info. We co-allocate the ArgInfos. FI = CGFunctionInfo::create(CC, instanceMethod, chainCall, info, - resultType, argTypes, required); + paramInfos, resultType, argTypes, required); FunctionInfos.InsertNode(FI, insertPos); bool inserted = FunctionsBeingProcessed.insert(FI).second; (void)inserted; assert(inserted && "Recursively being processed?"); - + // Compute ABI information. - getABIInfo().computeInfo(*FI); + if (CC == llvm::CallingConv::SPIR_KERNEL) { + // Force target independent argument handling for the host visible + // kernel functions. + computeSPIRKernelABIInfo(CGM, *FI); + } else if (info.getCC() == CC_Swift) { + swiftcall::computeABIInfo(CGM, *FI); + } else { + getABIInfo().computeInfo(*FI); + } // Loop over all of the computed argument and return value info. If any of // them are direct or extend without a specified coerce type, specify the @@ -573,11 +791,16 @@ bool instanceMethod, bool chainCall, const FunctionType::ExtInfo &info, + ArrayRef<ExtParameterInfo> paramInfos, CanQualType resultType, ArrayRef<CanQualType> argTypes, RequiredArgs required) { - void *buffer = operator new(sizeof(CGFunctionInfo) + - sizeof(ArgInfo) * (argTypes.size() + 1)); + assert(paramInfos.empty() || paramInfos.size() == argTypes.size()); + + void *buffer = + operator new(totalSizeToAlloc<ArgInfo, ExtParameterInfo>( + argTypes.size() + 1, paramInfos.size())); + CGFunctionInfo *FI = new(buffer) CGFunctionInfo(); FI->CallingConvention = llvmCC; FI->EffectiveCallingConvention = llvmCC; @@ -586,15 +809,19 @@ FI->ChainCall = chainCall; FI->NoReturn = info.getNoReturn(); FI->ReturnsRetained = info.getProducesResult(); + FI->NoCallerSavedRegs = info.getNoCallerSavedRegs(); FI->Required = required; FI->HasRegParm = info.getHasRegParm(); FI->RegParm = info.getRegParm(); FI->ArgStruct = nullptr; FI->ArgStructAlign = 0; FI->NumArgs = argTypes.size(); + FI->HasExtParameterInfos = !paramInfos.empty(); FI->getArgsBuffer()[0].type = resultType; for (unsigned i = 0, e = argTypes.size(); i != e; ++i) FI->getArgsBuffer()[i + 1].type = argTypes[i]; + for (unsigned i = 0, e = paramInfos.size(); i != e; ++i) + FI->getExtParameterInfosBuffer()[i] = paramInfos[i]; return FI; } @@ -641,7 +868,8 @@ RecordExpansion(SmallVector<const CXXBaseSpecifier *, 1> &&Bases, SmallVector<const FieldDecl *, 1> &&Fields) - : TypeExpansion(TEK_Record), Bases(Bases), Fields(Fields) {} + : TypeExpansion(TEK_Record), Bases(std::move(Bases)), + Fields(std::move(Fields)) {} static bool classof(const TypeExpansion *TE) { return TE->Kind == TEK_Record; } @@ -780,7 +1008,7 @@ } void CodeGenFunction::ExpandTypeFromArgs( - QualType Ty, LValue LV, SmallVectorImpl<llvm::Argument *>::iterator &AI) { + QualType Ty, LValue LV, SmallVectorImpl<llvm::Value *>::iterator &AI) { assert(LV.isSimple() && "Unexpected non-simple lvalue during struct expansion."); @@ -805,7 +1033,7 @@ } for (auto FD : RExp->Fields) { // FIXME: What are the right qualifiers here? - LValue SubLV = EmitLValueForField(LV, FD); + LValue SubLV = EmitLValueForFieldInitialization(LV, FD); ExpandTypeFromArgs(FD->getType(), SubLV, AI); } } else if (isa<ComplexExpansion>(Exp.get())) { @@ -1006,7 +1234,8 @@ // // FIXME: Assert that we aren't truncating non-padding bits when have access // to that information. - Src = CGF.Builder.CreateBitCast(Src, llvm::PointerType::getUnqual(Ty)); + Src = CGF.Builder.CreateBitCast(Src, + Ty->getPointerTo(Src.getAddressSpace())); return CGF.Builder.CreateLoad(Src); } @@ -1080,7 +1309,7 @@ // If store is legal, just bitcast the src pointer. if (SrcSize <= DstSize) { - Dst = CGF.Builder.CreateBitCast(Dst, llvm::PointerType::getUnqual(SrcTy)); + Dst = CGF.Builder.CreateElementBitCast(Dst, SrcTy); BuildAggStore(CGF, Src, Dst, DstIsVolatile); } else { // Otherwise do coercion through memory. This is stupid, but @@ -1227,11 +1456,13 @@ // ignore and inalloca doesn't have matching LLVM parameters. IRArgs.NumberOfArgs = 0; break; - case ABIArgInfo::Expand: { + case ABIArgInfo::CoerceAndExpand: + IRArgs.NumberOfArgs = AI.getCoerceAndExpandTypeSequence().size(); + break; + case ABIArgInfo::Expand: IRArgs.NumberOfArgs = getExpansionSize(ArgType, Context); break; } - } if (IRArgs.NumberOfArgs > 0) { IRArgs.FirstArgIndex = IRArgNo; @@ -1337,6 +1568,10 @@ resultType = llvm::Type::getVoidTy(getLLVMContext()); #endif break; + + case ABIArgInfo::CoerceAndExpand: + resultType = retAI.getUnpaddedCoerceAndExpandType(); + break; } ClangToLLVMArgMapping IRFunctionArgs(getContext(), FI, true); @@ -1381,9 +1616,10 @@ case ABIArgInfo::Indirect: { assert(NumIRArgs == 1); - // indirect arguments are always on the stack, which is addr space #0. + // indirect arguments are always on the stack, which is alloca addr space. llvm::Type *LTy = ConvertTypeForMem(it->type); - ArgTypes[FirstIRArg] = LTy->getPointerTo(); + ArgTypes[FirstIRArg] = LTy->getPointerTo( + CGM.getDataLayout().getAllocaAddrSpace()); break; } @@ -1404,6 +1640,15 @@ break; } + case ABIArgInfo::CoerceAndExpand: { + auto ArgTypesIter = ArgTypes.begin() + FirstIRArg; + for (auto EltTy : ArgInfo.getCoerceAndExpandTypeSequence()) { + *ArgTypesIter++ = EltTy; + } + assert(ArgTypesIter == ArgTypes.begin() + FirstIRArg + NumIRArgs); + break; + } + case ABIArgInfo::Expand: auto ArgTypesIter = ArgTypes.begin() + FirstIRArg; getExpandedTypes(it->type, ArgTypesIter); @@ -1445,15 +1690,118 @@ FuncAttrs.addAttribute(llvm::Attribute::NoUnwind); } +void CodeGenModule::ConstructDefaultFnAttrList(StringRef Name, bool HasOptnone, + bool AttrOnCallSite, + llvm::AttrBuilder &FuncAttrs) { + // OptimizeNoneAttr takes precedence over -Os or -Oz. No warning needed. + if (!HasOptnone) { + if (CodeGenOpts.OptimizeSize) + FuncAttrs.addAttribute(llvm::Attribute::OptimizeForSize); + if (CodeGenOpts.OptimizeSize == 2) + FuncAttrs.addAttribute(llvm::Attribute::MinSize); + } + + if (CodeGenOpts.DisableRedZone) + FuncAttrs.addAttribute(llvm::Attribute::NoRedZone); + if (CodeGenOpts.NoImplicitFloat) + FuncAttrs.addAttribute(llvm::Attribute::NoImplicitFloat); + + if (AttrOnCallSite) { + // Attributes that should go on the call site only. + if (!CodeGenOpts.SimplifyLibCalls || + CodeGenOpts.isNoBuiltinFunc(Name.data())) + FuncAttrs.addAttribute(llvm::Attribute::NoBuiltin); + if (!CodeGenOpts.TrapFuncName.empty()) + FuncAttrs.addAttribute("trap-func-name", CodeGenOpts.TrapFuncName); + } else { + // Attributes that should go on the function, but not the call site. + if (!CodeGenOpts.DisableFPElim) { + FuncAttrs.addAttribute("no-frame-pointer-elim", "false"); +#ifndef noCbC + } else if (CodeGenOpts.OmitLeafFramePointer || LangOpts.HasCodeSegment) { +#else + } else if (CodeGenOpts.OmitLeafFramePointer) { +#endif + FuncAttrs.addAttribute("no-frame-pointer-elim", "false"); + FuncAttrs.addAttribute("no-frame-pointer-elim-non-leaf"); + } else { + FuncAttrs.addAttribute("no-frame-pointer-elim", "true"); + FuncAttrs.addAttribute("no-frame-pointer-elim-non-leaf"); + } + + FuncAttrs.addAttribute("less-precise-fpmad", + llvm::toStringRef(CodeGenOpts.LessPreciseFPMAD)); + + if (!CodeGenOpts.FPDenormalMode.empty()) + FuncAttrs.addAttribute("denormal-fp-math", CodeGenOpts.FPDenormalMode); + + FuncAttrs.addAttribute("no-trapping-math", + llvm::toStringRef(CodeGenOpts.NoTrappingMath)); + + // TODO: Are these all needed? + // unsafe/inf/nan/nsz are handled by instruction-level FastMathFlags. + FuncAttrs.addAttribute("no-infs-fp-math", + llvm::toStringRef(CodeGenOpts.NoInfsFPMath)); + FuncAttrs.addAttribute("no-nans-fp-math", + llvm::toStringRef(CodeGenOpts.NoNaNsFPMath)); + FuncAttrs.addAttribute("unsafe-fp-math", + llvm::toStringRef(CodeGenOpts.UnsafeFPMath)); + FuncAttrs.addAttribute("use-soft-float", + llvm::toStringRef(CodeGenOpts.SoftFloat)); + FuncAttrs.addAttribute("stack-protector-buffer-size", + llvm::utostr(CodeGenOpts.SSPBufferSize)); + FuncAttrs.addAttribute("no-signed-zeros-fp-math", + llvm::toStringRef(CodeGenOpts.NoSignedZeros)); + FuncAttrs.addAttribute( + "correctly-rounded-divide-sqrt-fp-math", + llvm::toStringRef(CodeGenOpts.CorrectlyRoundedDivSqrt)); + + // TODO: Reciprocal estimate codegen options should apply to instructions? + std::vector<std::string> &Recips = getTarget().getTargetOpts().Reciprocals; + if (!Recips.empty()) + FuncAttrs.addAttribute("reciprocal-estimates", + llvm::join(Recips.begin(), Recips.end(), ",")); + + if (CodeGenOpts.StackRealignment) + FuncAttrs.addAttribute("stackrealign"); + if (CodeGenOpts.Backchain) + FuncAttrs.addAttribute("backchain"); + } + + if (getLangOpts().assumeFunctionsAreConvergent()) { + // Conservatively, mark all functions and calls in CUDA and OpenCL as + // convergent (meaning, they may call an intrinsically convergent op, such + // as __syncthreads() / barrier(), and so can't have certain optimizations + // applied around them). LLVM will remove this attribute where it safely + // can. + FuncAttrs.addAttribute(llvm::Attribute::Convergent); + } + + if (getLangOpts().CUDA && getLangOpts().CUDAIsDevice) { + // Exceptions aren't supported in CUDA device code. + FuncAttrs.addAttribute(llvm::Attribute::NoUnwind); + + // Respect -fcuda-flush-denormals-to-zero. + if (getLangOpts().CUDADeviceFlushDenormalsToZero) + FuncAttrs.addAttribute("nvptx-f32ftz", "true"); + } +} + +void CodeGenModule::AddDefaultFnAttrs(llvm::Function &F) { + llvm::AttrBuilder FuncAttrs; + ConstructDefaultFnAttrList(F.getName(), + F.hasFnAttribute(llvm::Attribute::OptimizeNone), + /* AttrOnCallsite = */ false, FuncAttrs); + F.addAttributes(llvm::AttributeList::FunctionIndex, FuncAttrs); +} + void CodeGenModule::ConstructAttributeList( StringRef Name, const CGFunctionInfo &FI, CGCalleeInfo CalleeInfo, - AttributeListType &PAL, unsigned &CallingConv, bool AttrOnCallSite) { + llvm::AttributeList &AttrList, unsigned &CallingConv, bool AttrOnCallSite) { llvm::AttrBuilder FuncAttrs; llvm::AttrBuilder RetAttrs; - bool HasOptnone = false; CallingConv = FI.getEffectiveCallingConvention(); - if (FI.isNoReturn()) FuncAttrs.addAttribute(llvm::Attribute::NoReturn); @@ -1464,6 +1812,7 @@ const Decl *TargetDecl = CalleeInfo.getCalleeDecl(); + bool HasOptnone = false; // FIXME: handle sseregparm someday... if (TargetDecl) { if (TargetDecl->hasAttr<ReturnsTwiceAttr>()) @@ -1472,8 +1821,12 @@ FuncAttrs.addAttribute(llvm::Attribute::NoUnwind); if (TargetDecl->hasAttr<NoReturnAttr>()) FuncAttrs.addAttribute(llvm::Attribute::NoReturn); + if (TargetDecl->hasAttr<ColdAttr>()) + FuncAttrs.addAttribute(llvm::Attribute::Cold); if (TargetDecl->hasAttr<NoDuplicateAttr>()) FuncAttrs.addAttribute(llvm::Attribute::NoDuplicate); + if (TargetDecl->hasAttr<ConvergentAttr>()) + FuncAttrs.addAttribute(llvm::Attribute::Convergent); if (const FunctionDecl *Fn = dyn_cast<FunctionDecl>(TargetDecl)) { AddAttributesFromFunctionProtoType( @@ -1500,71 +1853,34 @@ RetAttrs.addAttribute(llvm::Attribute::NoAlias); if (TargetDecl->hasAttr<ReturnsNonNullAttr>()) RetAttrs.addAttribute(llvm::Attribute::NonNull); + if (TargetDecl->hasAttr<AnyX86NoCallerSavedRegistersAttr>()) + FuncAttrs.addAttribute("no_caller_saved_registers"); HasOptnone = TargetDecl->hasAttr<OptimizeNoneAttr>(); + if (auto *AllocSize = TargetDecl->getAttr<AllocSizeAttr>()) { + Optional<unsigned> NumElemsParam; + // alloc_size args are base-1, 0 means not present. + if (unsigned N = AllocSize->getNumElemsParam()) + NumElemsParam = N - 1; + FuncAttrs.addAllocSizeAttr(AllocSize->getElemSizeParam() - 1, + NumElemsParam); + } } - // OptimizeNoneAttr takes precedence over -Os or -Oz. No warning needed. - if (!HasOptnone) { - if (CodeGenOpts.OptimizeSize) - FuncAttrs.addAttribute(llvm::Attribute::OptimizeForSize); - if (CodeGenOpts.OptimizeSize == 2) - FuncAttrs.addAttribute(llvm::Attribute::MinSize); - } - - if (CodeGenOpts.DisableRedZone) - FuncAttrs.addAttribute(llvm::Attribute::NoRedZone); - if (CodeGenOpts.NoImplicitFloat) - FuncAttrs.addAttribute(llvm::Attribute::NoImplicitFloat); + ConstructDefaultFnAttrList(Name, HasOptnone, AttrOnCallSite, FuncAttrs); + if (CodeGenOpts.EnableSegmentedStacks && !(TargetDecl && TargetDecl->hasAttr<NoSplitStackAttr>())) FuncAttrs.addAttribute("split-stack"); - if (AttrOnCallSite) { - // Attributes that should go on the call site only. - if (!CodeGenOpts.SimplifyLibCalls || - CodeGenOpts.isNoBuiltinFunc(Name.data())) - FuncAttrs.addAttribute(llvm::Attribute::NoBuiltin); - if (!CodeGenOpts.TrapFuncName.empty()) - FuncAttrs.addAttribute("trap-func-name", CodeGenOpts.TrapFuncName); - } else { - // Attributes that should go on the function, but not the call site. - if (!CodeGenOpts.DisableFPElim) { - FuncAttrs.addAttribute("no-frame-pointer-elim", "false"); -#ifndef noCbC - } else if (CodeGenOpts.OmitLeafFramePointer || LangOpts.HasCodeSegment) { -#else - } else if (CodeGenOpts.OmitLeafFramePointer) { -#endif - FuncAttrs.addAttribute("no-frame-pointer-elim", "false"); - FuncAttrs.addAttribute("no-frame-pointer-elim-non-leaf"); - } else { - FuncAttrs.addAttribute("no-frame-pointer-elim", "true"); - FuncAttrs.addAttribute("no-frame-pointer-elim-non-leaf"); - } - + if (!AttrOnCallSite) { bool DisableTailCalls = CodeGenOpts.DisableTailCalls || - (TargetDecl && TargetDecl->hasAttr<DisableTailCallsAttr>()); + (TargetDecl && (TargetDecl->hasAttr<DisableTailCallsAttr>() || + TargetDecl->hasAttr<AnyX86InterruptAttr>())); FuncAttrs.addAttribute("disable-tail-calls", llvm::toStringRef(DisableTailCalls)); - FuncAttrs.addAttribute("less-precise-fpmad", - llvm::toStringRef(CodeGenOpts.LessPreciseFPMAD)); - FuncAttrs.addAttribute("no-infs-fp-math", - llvm::toStringRef(CodeGenOpts.NoInfsFPMath)); - FuncAttrs.addAttribute("no-nans-fp-math", - llvm::toStringRef(CodeGenOpts.NoNaNsFPMath)); - FuncAttrs.addAttribute("unsafe-fp-math", - llvm::toStringRef(CodeGenOpts.UnsafeFPMath)); - FuncAttrs.addAttribute("use-soft-float", - llvm::toStringRef(CodeGenOpts.SoftFloat)); - FuncAttrs.addAttribute("stack-protector-buffer-size", - llvm::utostr(CodeGenOpts.SSPBufferSize)); - - if (CodeGenOpts.StackRealignment) - FuncAttrs.addAttribute("stackrealign"); - // Add target-cpu and target-features attributes to functions. If // we have a decl for the function and it has a target attribute then // parse that and add it to the feature set. @@ -1587,8 +1903,8 @@ // the function. const auto *TD = FD->getAttr<TargetAttr>(); TargetAttr::ParsedTargetAttr ParsedAttr = TD->parse(); - if (ParsedAttr.second != "") - TargetCPU = ParsedAttr.second; + if (ParsedAttr.Architecture != "") + TargetCPU = ParsedAttr.Architecture; if (TargetCPU != "") FuncAttrs.addAttribute("target-cpu", TargetCPU); if (!Features.empty()) { @@ -1638,6 +1954,9 @@ break; } + case ABIArgInfo::CoerceAndExpand: + break; + case ABIArgInfo::Expand: llvm_unreachable("Invalid ABI kind for return argument"); } @@ -1651,28 +1970,26 @@ RetAttrs.addAttribute(llvm::Attribute::NonNull); } - // Attach return attributes. - if (RetAttrs.hasAttributes()) { - PAL.push_back(llvm::AttributeSet::get( - getLLVMContext(), llvm::AttributeSet::ReturnIndex, RetAttrs)); - } + bool hasUsedSRet = false; + SmallVector<llvm::AttributeSet, 4> ArgAttrs(IRFunctionArgs.totalIRArgs()); // Attach attributes to sret. if (IRFunctionArgs.hasSRetArg()) { llvm::AttrBuilder SRETAttrs; SRETAttrs.addAttribute(llvm::Attribute::StructRet); + hasUsedSRet = true; if (RetAI.getInReg()) SRETAttrs.addAttribute(llvm::Attribute::InReg); - PAL.push_back(llvm::AttributeSet::get( - getLLVMContext(), IRFunctionArgs.getSRetArgNo() + 1, SRETAttrs)); + ArgAttrs[IRFunctionArgs.getSRetArgNo()] = + llvm::AttributeSet::get(getLLVMContext(), SRETAttrs); } // Attach attributes to inalloca argument. if (IRFunctionArgs.hasInallocaArg()) { llvm::AttrBuilder Attrs; Attrs.addAttribute(llvm::Attribute::InAlloca); - PAL.push_back(llvm::AttributeSet::get( - getLLVMContext(), IRFunctionArgs.getInallocaArgNo() + 1, Attrs)); + ArgAttrs[IRFunctionArgs.getInallocaArgNo()] = + llvm::AttributeSet::get(getLLVMContext(), Attrs); } unsigned ArgNo = 0; @@ -1685,10 +2002,12 @@ // Add attribute for padding argument, if necessary. if (IRFunctionArgs.hasPaddingArg(ArgNo)) { - if (AI.getPaddingInReg()) - PAL.push_back(llvm::AttributeSet::get( - getLLVMContext(), IRFunctionArgs.getPaddingArgNo(ArgNo) + 1, - llvm::Attribute::InReg)); + if (AI.getPaddingInReg()) { + ArgAttrs[IRFunctionArgs.getPaddingArgNo(ArgNo)] = + llvm::AttributeSet::get( + getLLVMContext(), + llvm::AttrBuilder().addAttribute(llvm::Attribute::InReg)); + } } // 'restrict' -> 'noalias' is done in EmitFunctionProlog when we @@ -1745,7 +2064,8 @@ } case ABIArgInfo::Ignore: case ABIArgInfo::Expand: - continue; + case ABIArgInfo::CoerceAndExpand: + break; case ABIArgInfo::InAlloca: // inalloca disables readnone and readonly. @@ -1763,21 +2083,57 @@ Attrs.addAttribute(llvm::Attribute::NonNull); } + switch (FI.getExtParameterInfo(ArgNo).getABI()) { + case ParameterABI::Ordinary: + break; + + case ParameterABI::SwiftIndirectResult: { + // Add 'sret' if we haven't already used it for something, but + // only if the result is void. + if (!hasUsedSRet && RetTy->isVoidType()) { + Attrs.addAttribute(llvm::Attribute::StructRet); + hasUsedSRet = true; + } + + // Add 'noalias' in either case. + Attrs.addAttribute(llvm::Attribute::NoAlias); + + // Add 'dereferenceable' and 'alignment'. + auto PTy = ParamType->getPointeeType(); + if (!PTy->isIncompleteType() && PTy->isConstantSizeType()) { + auto info = getContext().getTypeInfoInChars(PTy); + Attrs.addDereferenceableAttr(info.first.getQuantity()); + Attrs.addAttribute(llvm::Attribute::getWithAlignment(getLLVMContext(), + info.second.getQuantity())); + } + break; + } + + case ParameterABI::SwiftErrorResult: + Attrs.addAttribute(llvm::Attribute::SwiftError); + break; + + case ParameterABI::SwiftContext: + Attrs.addAttribute(llvm::Attribute::SwiftSelf); + break; + } + + if (FI.getExtParameterInfo(ArgNo).isNoEscape()) + Attrs.addAttribute(llvm::Attribute::NoCapture); + if (Attrs.hasAttributes()) { unsigned FirstIRArg, NumIRArgs; std::tie(FirstIRArg, NumIRArgs) = IRFunctionArgs.getIRArgs(ArgNo); for (unsigned i = 0; i < NumIRArgs; i++) - PAL.push_back(llvm::AttributeSet::get(getLLVMContext(), - FirstIRArg + i + 1, Attrs)); + ArgAttrs[FirstIRArg + i] = + llvm::AttributeSet::get(getLLVMContext(), Attrs); } } assert(ArgNo == FI.arg_size()); - if (FuncAttrs.hasAttributes()) - PAL.push_back(llvm:: - AttributeSet::get(getLLVMContext(), - llvm::AttributeSet::FunctionIndex, - FuncAttrs)); + AttrList = llvm::AttributeList::get( + getLLVMContext(), llvm::AttributeSet::get(getLLVMContext(), FuncAttrs), + llvm::AttributeSet::get(getLLVMContext(), RetAttrs), ArgAttrs); } /// An argument came in as a promoted argument; demote it back to its @@ -1828,6 +2184,18 @@ return nullptr; } +namespace { + struct CopyBackSwiftError final : EHScopeStack::Cleanup { + Address Temp; + Address Arg; + CopyBackSwiftError(Address temp, Address arg) : Temp(temp), Arg(arg) {} + void Emit(CodeGenFunction &CGF, Flags flags) override { + llvm::Value *errorValue = CGF.Builder.CreateLoad(Temp); + CGF.Builder.CreateStore(errorValue, Arg); + } + }; +} + void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, llvm::Function *Fn, const FunctionArgList &Args) { @@ -1853,7 +2221,7 @@ ClangToLLVMArgMapping IRFunctionArgs(CGM.getContext(), FI); // Flattened function arguments. - SmallVector<llvm::Argument *, 16> FnArgs; + SmallVector<llvm::Value *, 16> FnArgs; FnArgs.reserve(IRFunctionArgs.totalIRArgs()); for (auto &Arg : Fn->args()) { FnArgs.push_back(&Arg); @@ -1874,10 +2242,9 @@ // Name the struct return parameter. if (IRFunctionArgs.hasSRetArg()) { - auto AI = FnArgs[IRFunctionArgs.getSRetArgNo()]; + auto AI = cast<llvm::Argument>(FnArgs[IRFunctionArgs.getSRetArgNo()]); AI->setName("agg.result"); - AI->addAttr(llvm::AttributeSet::get(getLLVMContext(), AI->getArgNo() + 1, - llvm::Attribute::NoAlias)); + AI->addAttr(llvm::Attribute::NoAlias); } // Track if we received the parameter as a pointer (indirect, byval, or @@ -1962,15 +2329,13 @@ ArgI.getCoerceToType() == ConvertType(Ty) && ArgI.getDirectOffset() == 0) { assert(NumIRArgs == 1); - auto AI = FnArgs[FirstIRArg]; - llvm::Value *V = AI; + llvm::Value *V = FnArgs[FirstIRArg]; + auto AI = cast<llvm::Argument>(V); if (const ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(Arg)) { if (getNonNullAttr(CurCodeDecl, PVD, PVD->getType(), PVD->getFunctionScopeIndex())) - AI->addAttr(llvm::AttributeSet::get(getLLVMContext(), - AI->getArgNo() + 1, - llvm::Attribute::NonNull)); + AI->addAttr(llvm::Attribute::NonNull); QualType OTy = PVD->getOriginalType(); if (const auto *ArrTy = @@ -1987,12 +2352,9 @@ llvm::AttrBuilder Attrs; Attrs.addDereferenceableAttr( getContext().getTypeSizeInChars(ETy).getQuantity()*ArrSize); - AI->addAttr(llvm::AttributeSet::get(getLLVMContext(), - AI->getArgNo() + 1, Attrs)); + AI->addAttrs(Attrs); } else if (getContext().getTargetAddressSpace(ETy) == 0) { - AI->addAttr(llvm::AttributeSet::get(getLLVMContext(), - AI->getArgNo() + 1, - llvm::Attribute::NonNull)); + AI->addAttr(llvm::Attribute::NonNull); } } } else if (const auto *ArrTy = @@ -2002,35 +2364,45 @@ // we know that it must be nonnull. if (ArrTy->getSizeModifier() == VariableArrayType::Static && !getContext().getTargetAddressSpace(ArrTy->getElementType())) - AI->addAttr(llvm::AttributeSet::get(getLLVMContext(), - AI->getArgNo() + 1, - llvm::Attribute::NonNull)); + AI->addAttr(llvm::Attribute::NonNull); } const auto *AVAttr = PVD->getAttr<AlignValueAttr>(); if (!AVAttr) if (const auto *TOTy = dyn_cast<TypedefType>(OTy)) AVAttr = TOTy->getDecl()->getAttr<AlignValueAttr>(); - if (AVAttr) { + if (AVAttr) { llvm::Value *AlignmentValue = EmitScalarExpr(AVAttr->getAlignment()); llvm::ConstantInt *AlignmentCI = cast<llvm::ConstantInt>(AlignmentValue); - unsigned Alignment = - std::min((unsigned) AlignmentCI->getZExtValue(), - +llvm::Value::MaximumAlignment); - - llvm::AttrBuilder Attrs; - Attrs.addAlignmentAttr(Alignment); - AI->addAttr(llvm::AttributeSet::get(getLLVMContext(), - AI->getArgNo() + 1, Attrs)); + unsigned Alignment = std::min((unsigned)AlignmentCI->getZExtValue(), + +llvm::Value::MaximumAlignment); + AI->addAttrs(llvm::AttrBuilder().addAlignmentAttr(Alignment)); } } if (Arg->getType().isRestrictQualified()) - AI->addAttr(llvm::AttributeSet::get(getLLVMContext(), - AI->getArgNo() + 1, - llvm::Attribute::NoAlias)); + AI->addAttr(llvm::Attribute::NoAlias); + + // LLVM expects swifterror parameters to be used in very restricted + // ways. Copy the value into a less-restricted temporary. + if (FI.getExtParameterInfo(ArgNo).getABI() + == ParameterABI::SwiftErrorResult) { + QualType pointeeTy = Ty->getPointeeType(); + assert(pointeeTy->isPointerType()); + Address temp = + CreateMemTemp(pointeeTy, getPointerAlign(), "swifterror.temp"); + Address arg = Address(V, getContext().getTypeAlignInChars(pointeeTy)); + llvm::Value *incomingErrorValue = Builder.CreateLoad(arg); + Builder.CreateStore(incomingErrorValue, temp); + V = temp.getPointer(); + + // Push a cleanup to copy the value back at the end of the function. + // The convention does not guarantee that the value will be written + // back if the function exits with an unwind exception. + EHStack.pushCleanup<CopyBackSwiftError>(NormalCleanup, temp, arg); + } // Ensure the argument is the correct type. if (V->getType() != ArgI.getCoerceToType()) @@ -2039,13 +2411,6 @@ if (isPromoted) V = emitArgumentDemotion(*this, Arg, V); - if (const CXXMethodDecl *MD = - dyn_cast_or_null<CXXMethodDecl>(CurCodeDecl)) { - if (MD->isVirtual() && Arg == CXXABIThisDecl) - V = CGM.getCXXABI(). - adjustThisParameterInVirtualFunctionPrologue(*this, CurGD, V); - } - // Because of merging of function types from multiple decls it is // possible for the type of an argument to not match the corresponding // type in the function type. Since we are codegening the callee @@ -2076,8 +2441,7 @@ Address AddrToStoreInto = Address::invalid(); if (SrcSize <= DstSize) { - AddrToStoreInto = - Builder.CreateBitCast(Ptr, llvm::PointerType::getUnqual(STy)); + AddrToStoreInto = Builder.CreateElementBitCast(Ptr, STy); } else { AddrToStoreInto = CreateTempAlloca(STy, Alloca.getAlignment(), "coerce"); @@ -2118,6 +2482,29 @@ break; } + case ABIArgInfo::CoerceAndExpand: { + // Reconstruct into a temporary. + Address alloca = CreateMemTemp(Ty, getContext().getDeclAlign(Arg)); + ArgVals.push_back(ParamValue::forIndirect(alloca)); + + auto coercionType = ArgI.getCoerceAndExpandType(); + alloca = Builder.CreateElementBitCast(alloca, coercionType); + auto layout = CGM.getDataLayout().getStructLayout(coercionType); + + unsigned argIndex = FirstIRArg; + for (unsigned i = 0, e = coercionType->getNumElements(); i != e; ++i) { + llvm::Type *eltType = coercionType->getElementType(i); + if (ABIArgInfo::isPaddingForCoerceAndExpand(eltType)) + continue; + + auto eltAddr = Builder.CreateStructGEP(alloca, i, layout); + auto elt = FnArgs[argIndex++]; + Builder.CreateStore(elt, eltAddr); + } + assert(argIndex == FirstIRArg + NumIRArgs); + break; + } + case ABIArgInfo::Expand: { // If this structure was expanded into multiple arguments then // we need to create a temporary and reconstruct it from the @@ -2182,7 +2569,7 @@ // result is in a BasicBlock and is therefore an Instruction. llvm::Instruction *generator = cast<llvm::Instruction>(result); - SmallVector<llvm::Instruction*,4> insnsToKill; + SmallVector<llvm::Instruction *, 4> InstsToKill; // Look for: // %generator = bitcast %type1* %generator2 to %type2* @@ -2195,7 +2582,7 @@ if (generator->getNextNode() != bitcast) return nullptr; - insnsToKill.push_back(bitcast); + InstsToKill.push_back(bitcast); } // Look for: @@ -2228,27 +2615,26 @@ assert(isa<llvm::CallInst>(prev)); assert(cast<llvm::CallInst>(prev)->getCalledValue() == CGF.CGM.getObjCEntrypoints().retainAutoreleasedReturnValueMarker); - insnsToKill.push_back(prev); + InstsToKill.push_back(prev); } } else { return nullptr; } result = call->getArgOperand(0); - insnsToKill.push_back(call); + InstsToKill.push_back(call); // Keep killing bitcasts, for sanity. Note that we no longer care // about precise ordering as long as there's exactly one use. while (llvm::BitCastInst *bitcast = dyn_cast<llvm::BitCastInst>(result)) { if (!bitcast->hasOneUse()) break; - insnsToKill.push_back(bitcast); + InstsToKill.push_back(bitcast); result = bitcast->getOperand(0); } // Delete all the unnecessary instructions, from latest to earliest. - for (SmallVectorImpl<llvm::Instruction*>::iterator - i = insnsToKill.begin(), e = insnsToKill.end(); i != e; ++i) - (*i)->eraseFromParent(); + for (auto *I : InstsToKill) + I->eraseFromParent(); // Do the fused retain/autorelease if we were asked to. if (doRetainAutorelease) @@ -2480,9 +2866,26 @@ // In ARC, end functions that return a retainable type with a call // to objc_autoreleaseReturnValue. if (AutoreleaseResult) { +#ifndef NDEBUG + // Type::isObjCRetainabletype has to be called on a QualType that hasn't + // been stripped of the typedefs, so we cannot use RetTy here. Get the + // original return type of FunctionDecl, CurCodeDecl, and BlockDecl from + // CurCodeDecl or BlockInfo. + QualType RT; + + if (auto *FD = dyn_cast<FunctionDecl>(CurCodeDecl)) + RT = FD->getReturnType(); + else if (auto *MD = dyn_cast<ObjCMethodDecl>(CurCodeDecl)) + RT = MD->getReturnType(); + else if (isa<BlockDecl>(CurCodeDecl)) + RT = BlockInfo->BlockExpression->getFunctionType()->getReturnType(); + else + llvm_unreachable("Unexpected function/method type"); + assert(getLangOpts().ObjCAutoRefCount && !FI.isReturnsRetained() && - RetTy->isObjCRetainableType()); + RT->isObjCRetainableType()); +#endif RV = emitAutoreleaseOfResult(*this, RV); } @@ -2491,25 +2894,47 @@ case ABIArgInfo::Ignore: break; + case ABIArgInfo::CoerceAndExpand: { + auto coercionType = RetAI.getCoerceAndExpandType(); + auto layout = CGM.getDataLayout().getStructLayout(coercionType); + + // Load all of the coerced elements out into results. + llvm::SmallVector<llvm::Value*, 4> results; + Address addr = Builder.CreateElementBitCast(ReturnValue, coercionType); + for (unsigned i = 0, e = coercionType->getNumElements(); i != e; ++i) { + auto coercedEltType = coercionType->getElementType(i); + if (ABIArgInfo::isPaddingForCoerceAndExpand(coercedEltType)) + continue; + + auto eltAddr = Builder.CreateStructGEP(addr, i, layout); + auto elt = Builder.CreateLoad(eltAddr); + results.push_back(elt); + } + + // If we have one result, it's the single direct result type. + if (results.size() == 1) { + RV = results[0]; + + // Otherwise, we need to make a first-class aggregate. + } else { + // Construct a return type that lacks padding elements. + llvm::Type *returnType = RetAI.getUnpaddedCoerceAndExpandType(); + + RV = llvm::UndefValue::get(returnType); + for (unsigned i = 0, e = results.size(); i != e; ++i) { + RV = Builder.CreateInsertValue(RV, results[i], i); + } + } + break; + } + case ABIArgInfo::Expand: llvm_unreachable("Invalid ABI kind for return argument"); } llvm::Instruction *Ret; if (RV) { - if (CurCodeDecl && SanOpts.has(SanitizerKind::ReturnsNonnullAttribute)) { - if (auto RetNNAttr = CurCodeDecl->getAttr<ReturnsNonNullAttr>()) { - SanitizerScope SanScope(this); - llvm::Value *Cond = Builder.CreateICmpNE( - RV, llvm::Constant::getNullValue(RV->getType())); - llvm::Constant *StaticData[] = { - EmitCheckSourceLocation(EndLoc), - EmitCheckSourceLocation(RetNNAttr->getLocation()), - }; - EmitCheck(std::make_pair(Cond, SanitizerKind::ReturnsNonnullAttribute), - "nonnull_return", StaticData, None); - } - } + EmitReturnValueCheck(RV); Ret = Builder.CreateRet(RV); } else { Ret = Builder.CreateRetVoid(); @@ -2519,6 +2944,65 @@ Ret->setDebugLoc(std::move(RetDbgLoc)); } +void CodeGenFunction::EmitReturnValueCheck(llvm::Value *RV) { + // A current decl may not be available when emitting vtable thunks. + if (!CurCodeDecl) + return; + + ReturnsNonNullAttr *RetNNAttr = nullptr; + if (SanOpts.has(SanitizerKind::ReturnsNonnullAttribute)) + RetNNAttr = CurCodeDecl->getAttr<ReturnsNonNullAttr>(); + + if (!RetNNAttr && !requiresReturnValueNullabilityCheck()) + return; + + // Prefer the returns_nonnull attribute if it's present. + SourceLocation AttrLoc; + SanitizerMask CheckKind; + SanitizerHandler Handler; + if (RetNNAttr) { + assert(!requiresReturnValueNullabilityCheck() && + "Cannot check nullability and the nonnull attribute"); + AttrLoc = RetNNAttr->getLocation(); + CheckKind = SanitizerKind::ReturnsNonnullAttribute; + Handler = SanitizerHandler::NonnullReturn; + } else { + if (auto *DD = dyn_cast<DeclaratorDecl>(CurCodeDecl)) + if (auto *TSI = DD->getTypeSourceInfo()) + if (auto FTL = TSI->getTypeLoc().castAs<FunctionTypeLoc>()) + AttrLoc = FTL.getReturnLoc().findNullabilityLoc(); + CheckKind = SanitizerKind::NullabilityReturn; + Handler = SanitizerHandler::NullabilityReturn; + } + + SanitizerScope SanScope(this); + + // Make sure the "return" source location is valid. If we're checking a + // nullability annotation, make sure the preconditions for the check are met. + llvm::BasicBlock *Check = createBasicBlock("nullcheck"); + llvm::BasicBlock *NoCheck = createBasicBlock("no.nullcheck"); + llvm::Value *SLocPtr = Builder.CreateLoad(ReturnLocation, "return.sloc.load"); + llvm::Value *CanNullCheck = Builder.CreateIsNotNull(SLocPtr); + if (requiresReturnValueNullabilityCheck()) + CanNullCheck = + Builder.CreateAnd(CanNullCheck, RetValNullabilityPrecondition); + Builder.CreateCondBr(CanNullCheck, Check, NoCheck); + EmitBlock(Check); + + // Now do the null check. + llvm::Value *Cond = Builder.CreateIsNotNull(RV); + llvm::Constant *StaticData[] = {EmitCheckSourceLocation(AttrLoc)}; + llvm::Value *DynamicData[] = {SLocPtr}; + EmitCheck(std::make_pair(Cond, CheckKind), Handler, StaticData, DynamicData); + + EmitBlock(NoCheck); + +#ifndef NDEBUG + // The return location should not be used after the check has been emitted. + ReturnLocation = Address::invalid(); +#endif +} + static bool isInAllocaArgument(CGCXXABI &ABI, QualType type) { const CXXRecordDecl *RD = type->getAsCXXRecordDecl(); return RD && ABI.getRecordArgABI(RD) == CGCXXABI::RAA_DirectInMemory; @@ -2529,13 +3013,13 @@ // FIXME: Generate IR in one pass, rather than going back and fixing up these // placeholders. llvm::Type *IRTy = CGF.ConvertTypeForMem(Ty); - llvm::Value *Placeholder = - llvm::UndefValue::get(IRTy->getPointerTo()->getPointerTo()); - Placeholder = CGF.Builder.CreateDefaultAlignedLoad(Placeholder); + llvm::Type *IRPtrTy = IRTy->getPointerTo(); + llvm::Value *Placeholder = llvm::UndefValue::get(IRPtrTy->getPointerTo()); // FIXME: When we generate this IR in one pass, we shouldn't need // this win32-specific alignment hack. CharUnits Align = CharUnits::fromQuantity(4); + Placeholder = CGF.Builder.CreateAlignedLoad(IRPtrTy, Placeholder, Align); return AggValueSlot::forAddr(Address(Placeholder, Align), Ty.getQualifiers(), @@ -2554,33 +3038,39 @@ QualType type = param->getType(); - // For the most part, we just need to load the alloca, except: - // 1) aggregate r-values are actually pointers to temporaries, and - // 2) references to non-scalars are pointers directly to the aggregate. - // I don't know why references to scalars are different here. - if (const ReferenceType *ref = type->getAs<ReferenceType>()) { - if (!hasScalarEvaluationKind(ref->getPointeeType())) - return args.add(RValue::getAggregate(local), type); - - // Locals which are references to scalars are represented - // with allocas holding the pointer. - return args.add(RValue::get(Builder.CreateLoad(local)), type); - } - assert(!isInAllocaArgument(CGM.getCXXABI(), type) && "cannot emit delegate call arguments for inalloca arguments!"); - args.add(convertTempToRValue(local, type, loc), type); + // GetAddrOfLocalVar returns a pointer-to-pointer for references, + // but the argument needs to be the original pointer. + if (type->isReferenceType()) { + args.add(RValue::get(Builder.CreateLoad(local)), type); + + // In ARC, move out of consumed arguments so that the release cleanup + // entered by StartFunction doesn't cause an over-release. This isn't + // optimal -O0 code generation, but it should get cleaned up when + // optimization is enabled. This also assumes that delegate calls are + // performed exactly once for a set of arguments, but that should be safe. + } else if (getLangOpts().ObjCAutoRefCount && + param->hasAttr<NSConsumedAttr>() && + type->isObjCRetainableType()) { + llvm::Value *ptr = Builder.CreateLoad(local); + auto null = + llvm::ConstantPointerNull::get(cast<llvm::PointerType>(ptr->getType())); + Builder.CreateStore(null, local); + args.add(RValue::get(ptr), type); + + // For the most part, we just need to load the alloca, except that + // aggregate r-values are actually pointers to temporaries. + } else { + args.add(convertTempToRValue(local, type, loc), type); + } } static bool isProvablyNull(llvm::Value *addr) { return isa<llvm::ConstantPointerNull>(addr); } -static bool isProvablyNonNull(llvm::Value *addr) { - return isa<llvm::AllocaInst>(addr); -} - /// Emit the actual writing-back of a writeback. static void emitWriteback(CodeGenFunction &CGF, const CallArgList::Writeback &writeback) { @@ -2593,7 +3083,8 @@ // If the argument wasn't provably non-null, we need to null check // before doing the store. - bool provablyNonNull = isProvablyNonNull(srcAddr.getPointer()); + bool provablyNonNull = llvm::isKnownNonZero(srcAddr.getPointer(), + CGF.CGM.getDataLayout()); if (!provablyNonNull) { llvm::BasicBlock *writebackBB = CGF.createBasicBlock("icr.writeback"); contBB = CGF.createBasicBlock("icr.done"); @@ -2733,7 +3224,8 @@ // If the address is *not* known to be non-null, we need to switch. llvm::Value *finalArgument; - bool provablyNonNull = isProvablyNonNull(srcAddr.getPointer()); + bool provablyNonNull = llvm::isKnownNonZero(srcAddr.getPointer(), + CGF.CGM.getDataLayout()); if (provablyNonNull) { finalArgument = temp.getPointer(); } else { @@ -2804,7 +3296,7 @@ } void CallArgList::allocateArgumentMemory(CodeGenFunction &CGF) { - assert(!StackBase && !StackCleanup.isValid()); + assert(!StackBase); // Save the stack. llvm::Function *F = CGF.CGM.getIntrinsic(llvm::Intrinsic::stacksave); @@ -2821,54 +3313,97 @@ void CodeGenFunction::EmitNonNullArgCheck(RValue RV, QualType ArgType, SourceLocation ArgLoc, - const FunctionDecl *FD, + AbstractCallee AC, unsigned ParmNum) { - if (!SanOpts.has(SanitizerKind::NonnullAttribute) || !FD) + if (!AC.getDecl() || !(SanOpts.has(SanitizerKind::NonnullAttribute) || + SanOpts.has(SanitizerKind::NullabilityArg))) return; - auto PVD = ParmNum < FD->getNumParams() ? FD->getParamDecl(ParmNum) : nullptr; + + // The param decl may be missing in a variadic function. + auto PVD = ParmNum < AC.getNumParams() ? AC.getParamDecl(ParmNum) : nullptr; unsigned ArgNo = PVD ? PVD->getFunctionScopeIndex() : ParmNum; - auto NNAttr = getNonNullAttr(FD, PVD, ArgType, ArgNo); - if (!NNAttr) + + // Prefer the nonnull attribute if it's present. + const NonNullAttr *NNAttr = nullptr; + if (SanOpts.has(SanitizerKind::NonnullAttribute)) + NNAttr = getNonNullAttr(AC.getDecl(), PVD, ArgType, ArgNo); + + bool CanCheckNullability = false; + if (SanOpts.has(SanitizerKind::NullabilityArg) && !NNAttr && PVD) { + auto Nullability = PVD->getType()->getNullability(getContext()); + CanCheckNullability = Nullability && + *Nullability == NullabilityKind::NonNull && + PVD->getTypeSourceInfo(); + } + + if (!NNAttr && !CanCheckNullability) return; + + SourceLocation AttrLoc; + SanitizerMask CheckKind; + SanitizerHandler Handler; + if (NNAttr) { + AttrLoc = NNAttr->getLocation(); + CheckKind = SanitizerKind::NonnullAttribute; + Handler = SanitizerHandler::NonnullArg; + } else { + AttrLoc = PVD->getTypeSourceInfo()->getTypeLoc().findNullabilityLoc(); + CheckKind = SanitizerKind::NullabilityArg; + Handler = SanitizerHandler::NullabilityArg; + } + SanitizerScope SanScope(this); assert(RV.isScalar()); llvm::Value *V = RV.getScalarVal(); llvm::Value *Cond = Builder.CreateICmpNE(V, llvm::Constant::getNullValue(V->getType())); llvm::Constant *StaticData[] = { - EmitCheckSourceLocation(ArgLoc), - EmitCheckSourceLocation(NNAttr->getLocation()), + EmitCheckSourceLocation(ArgLoc), EmitCheckSourceLocation(AttrLoc), llvm::ConstantInt::get(Int32Ty, ArgNo + 1), }; - EmitCheck(std::make_pair(Cond, SanitizerKind::NonnullAttribute), - "nonnull_arg", StaticData, None); + EmitCheck(std::make_pair(Cond, CheckKind), Handler, StaticData, None); } void CodeGenFunction::EmitCallArgs( CallArgList &Args, ArrayRef<QualType> ArgTypes, llvm::iterator_range<CallExpr::const_arg_iterator> ArgRange, - const FunctionDecl *CalleeDecl, unsigned ParamsToSkip) { + AbstractCallee AC, unsigned ParamsToSkip, EvaluationOrder Order) { assert((int)ArgTypes.size() == (ArgRange.end() - ArgRange.begin())); - auto MaybeEmitImplicitObjectSize = [&](unsigned I, const Expr *Arg) { - if (CalleeDecl == nullptr || I >= CalleeDecl->getNumParams()) + // We *have* to evaluate arguments from right to left in the MS C++ ABI, + // because arguments are destroyed left to right in the callee. As a special + // case, there are certain language constructs that require left-to-right + // evaluation, and in those cases we consider the evaluation order requirement + // to trump the "destruction order is reverse construction order" guarantee. + bool LeftToRight = + CGM.getTarget().getCXXABI().areArgsDestroyedLeftToRightInCallee() + ? Order == EvaluationOrder::ForceLeftToRight + : Order != EvaluationOrder::ForceRightToLeft; + + auto MaybeEmitImplicitObjectSize = [&](unsigned I, const Expr *Arg, + RValue EmittedArg) { + if (!AC.hasFunctionDecl() || I >= AC.getNumParams()) return; - auto *PS = CalleeDecl->getParamDecl(I)->getAttr<PassObjectSizeAttr>(); + auto *PS = AC.getParamDecl(I)->getAttr<PassObjectSizeAttr>(); if (PS == nullptr) return; const auto &Context = getContext(); auto SizeTy = Context.getSizeType(); auto T = Builder.getIntNTy(Context.getTypeSize(SizeTy)); - llvm::Value *V = evaluateOrEmitBuiltinObjectSize(Arg, PS->getType(), T); + assert(EmittedArg.getScalarVal() && "We emitted nothing for the arg?"); + llvm::Value *V = evaluateOrEmitBuiltinObjectSize(Arg, PS->getType(), T, + EmittedArg.getScalarVal()); Args.add(RValue::get(V), SizeTy); + // If we're emitting args in reverse, be sure to do so with + // pass_object_size, as well. + if (!LeftToRight) + std::swap(Args.back(), *(&Args.back() - 1)); }; - // We *have* to evaluate arguments from right to left in the MS C++ ABI, - // because arguments are destroyed left to right in the callee. - if (CGM.getTarget().getCXXABI().areArgsDestroyedLeftToRightInCallee()) { - // Insert a stack save if we're going to need any inalloca args. - bool HasInAllocaArgs = false; + // Insert a stack save if we're going to need any inalloca args. + bool HasInAllocaArgs = false; + if (CGM.getTarget().getCXXABI().isMicrosoft()) { for (ArrayRef<QualType>::iterator I = ArgTypes.begin(), E = ArgTypes.end(); I != E && !HasInAllocaArgs; ++I) HasInAllocaArgs = isInAllocaArgument(CGM.getCXXABI(), *I); @@ -2876,30 +3411,41 @@ assert(getTarget().getTriple().getArch() == llvm::Triple::x86); Args.allocateArgumentMemory(*this); } - - // Evaluate each argument. - size_t CallArgsStart = Args.size(); - for (int I = ArgTypes.size() - 1; I >= 0; --I) { - CallExpr::const_arg_iterator Arg = ArgRange.begin() + I; - EmitCallArg(Args, *Arg, ArgTypes[I]); - EmitNonNullArgCheck(Args.back().RV, ArgTypes[I], (*Arg)->getExprLoc(), - CalleeDecl, ParamsToSkip + I); - MaybeEmitImplicitObjectSize(I, *Arg); - } - + } + + // Evaluate each argument in the appropriate order. + size_t CallArgsStart = Args.size(); + for (unsigned I = 0, E = ArgTypes.size(); I != E; ++I) { + unsigned Idx = LeftToRight ? I : E - I - 1; + CallExpr::const_arg_iterator Arg = ArgRange.begin() + Idx; + unsigned InitialArgSize = Args.size(); + // If *Arg is an ObjCIndirectCopyRestoreExpr, check that either the types of + // the argument and parameter match or the objc method is parameterized. + assert((!isa<ObjCIndirectCopyRestoreExpr>(*Arg) || + getContext().hasSameUnqualifiedType((*Arg)->getType(), + ArgTypes[Idx]) || + (isa<ObjCMethodDecl>(AC.getDecl()) && + isObjCMethodWithTypeParams(cast<ObjCMethodDecl>(AC.getDecl())))) && + "Argument and parameter types don't match"); + EmitCallArg(Args, *Arg, ArgTypes[Idx]); + // In particular, we depend on it being the last arg in Args, and the + // objectsize bits depend on there only being one arg if !LeftToRight. + assert(InitialArgSize + 1 == Args.size() && + "The code below depends on only adding one arg per EmitCallArg"); + (void)InitialArgSize; + RValue RVArg = Args.back().RV; + EmitNonNullArgCheck(RVArg, ArgTypes[Idx], (*Arg)->getExprLoc(), AC, + ParamsToSkip + Idx); + // @llvm.objectsize should never have side-effects and shouldn't need + // destruction/cleanups, so we can safely "emit" it after its arg, + // regardless of right-to-leftness + MaybeEmitImplicitObjectSize(Idx, *Arg, RVArg); + } + + if (!LeftToRight) { // Un-reverse the arguments we just evaluated so they match up with the LLVM // IR function. std::reverse(Args.begin() + CallArgsStart, Args.end()); - return; - } - - for (unsigned I = 0, E = ArgTypes.size(); I != E; ++I) { - CallExpr::const_arg_iterator Arg = ArgRange.begin() + I; - assert(Arg != ArgRange.end()); - EmitCallArg(Args, *Arg, ArgTypes[I]); - EmitNonNullArgCheck(Args.back().RV, ArgTypes[I], (*Arg)->getExprLoc(), - CalleeDecl, ParamsToSkip + I); - MaybeEmitImplicitObjectSize(I, *Arg); } } @@ -2941,7 +3487,6 @@ if (const ObjCIndirectCopyRestoreExpr *CRE = dyn_cast<ObjCIndirectCopyRestoreExpr>(E)) { assert(getLangOpts().ObjCAutoRefCount); - assert(getContext().hasSameType(E->getType(), type)); return emitWritebackArg(*this, args, CRE); } @@ -3064,16 +3609,6 @@ return EmitRuntimeCall(callee, None, name); } -/// Emits a simple call (never an invoke) to the given runtime function. -llvm::CallInst * -CodeGenFunction::EmitRuntimeCall(llvm::Value *callee, - ArrayRef<llvm::Value*> args, - const llvm::Twine &name) { - llvm::CallInst *call = Builder.CreateCall(callee, args, name); - call->setCallingConv(getRuntimeCC()); - return call; -} - // Calls which may throw must have operand bundles indicating which funclet // they are nested within. static void @@ -3092,6 +3627,19 @@ BundleList.emplace_back("funclet", CurrentFuncletPad); } +/// Emits a simple call (never an invoke) to the given runtime function. +llvm::CallInst * +CodeGenFunction::EmitRuntimeCall(llvm::Value *callee, + ArrayRef<llvm::Value*> args, + const llvm::Twine &name) { + SmallVector<llvm::OperandBundleDef, 1> BundleList; + getBundlesForFunclet(callee, CurrentFuncletPad, BundleList); + + llvm::CallInst *call = Builder.CreateCall(callee, args, BundleList, name); + call->setCallingConv(getRuntimeCC()); + return call; +} + /// Emits a call or invoke to the given noreturn runtime function. void CodeGenFunction::EmitNoreturnRuntimeCallOrInvoke(llvm::Value *callee, ArrayRef<llvm::Value*> args) { @@ -3139,13 +3687,16 @@ ArrayRef<llvm::Value *> Args, const Twine &Name) { llvm::BasicBlock *InvokeDest = getInvokeDest(); + SmallVector<llvm::OperandBundleDef, 1> BundleList; + getBundlesForFunclet(Callee, CurrentFuncletPad, BundleList); llvm::Instruction *Inst; if (!InvokeDest) - Inst = Builder.CreateCall(Callee, Args, Name); + Inst = Builder.CreateCall(Callee, Args, BundleList, Name); else { llvm::BasicBlock *ContBB = createBasicBlock("invoke.cont"); - Inst = Builder.CreateInvoke(Callee, ContBB, InvokeDest, Args, Name); + Inst = Builder.CreateInvoke(Callee, ContBB, InvokeDest, Args, BundleList, + Name); EmitBlock(ContBB); } @@ -3173,33 +3724,36 @@ } RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, - llvm::Value *Callee, + const CGCallee &Callee, ReturnValueSlot ReturnValue, const CallArgList &CallArgs, - CGCalleeInfo CalleeInfo, llvm::Instruction **callOrInvoke) { // FIXME: We no longer need the types from CallArgs; lift up and simplify. + assert(Callee.isOrdinary()); + // Handle struct-return functions by passing a pointer to the // location that we would like to return into. QualType RetTy = CallInfo.getReturnType(); const ABIArgInfo &RetAI = CallInfo.getReturnInfo(); - llvm::FunctionType *IRFuncTy = - cast<llvm::FunctionType>( - cast<llvm::PointerType>(Callee->getType())->getElementType()); + llvm::FunctionType *IRFuncTy = Callee.getFunctionType(); + + // 1. Set up the arguments. // If we're using inalloca, insert the allocation after the stack save. // FIXME: Do this earlier rather than hacking it in here! Address ArgMemory = Address::invalid(); const llvm::StructLayout *ArgMemoryLayout = nullptr; if (llvm::StructType *ArgStruct = CallInfo.getArgStruct()) { - ArgMemoryLayout = CGM.getDataLayout().getStructLayout(ArgStruct); + const llvm::DataLayout &DL = CGM.getDataLayout(); + ArgMemoryLayout = DL.getStructLayout(ArgStruct); llvm::Instruction *IP = CallArgs.getStackBase(); llvm::AllocaInst *AI; if (IP) { IP = IP->getNextNode(); - AI = new llvm::AllocaInst(ArgStruct, "argmem", IP); + AI = new llvm::AllocaInst(ArgStruct, DL.getAllocaAddrSpace(), + "argmem", IP); } else { AI = CreateTempAlloca(ArgStruct, "argmem"); } @@ -3224,7 +3778,7 @@ // alloca to hold the result, unless one is given to us. Address SRetPtr = Address::invalid(); size_t UnusedReturnSize = 0; - if (RetAI.isIndirect() || RetAI.isInAlloca()) { + if (RetAI.isIndirect() || RetAI.isInAlloca() || RetAI.isCoerceAndExpand()) { if (!ReturnValue.isNull()) { SRetPtr = ReturnValue.getValue(); } else { @@ -3238,12 +3792,16 @@ } if (IRFunctionArgs.hasSRetArg()) { IRCallArgs[IRFunctionArgs.getSRetArgNo()] = SRetPtr.getPointer(); - } else { + } else if (RetAI.isInAlloca()) { Address Addr = createInAllocaStructGEP(RetAI.getInAllocaFieldIndex()); Builder.CreateStore(SRetPtr.getPointer(), Addr); } } + Address swiftErrorTemp = Address::invalid(); + Address swiftErrorArg = Address::invalid(); + + // Translate all of the arguments as necessary to match the IR lowering. assert(CallInfo.arg_size() == CallArgs.size() && "Mismatch between function signature & arguments."); unsigned ArgNo = 0; @@ -3294,7 +3852,8 @@ assert(NumIRArgs == 1); if (RV.isScalar() || RV.isComplex()) { // Make a temporary alloca to pass the argument. - Address Addr = CreateMemTemp(I->Ty, ArgInfo.getIndirectAlign()); + Address Addr = CreateMemTemp(I->Ty, ArgInfo.getIndirectAlign(), + "indirect-arg-temp", false); IRCallArgs[FirstIRArg] = Addr.getPointer(); LValue argLV = MakeAddrLValue(Addr, I->Ty); @@ -3323,7 +3882,8 @@ < Align.getQuantity()) || (ArgInfo.getIndirectByVal() && (RVAddrSpace != ArgAddrSpace))) { // Create an aligned temporary, and copy to it. - Address AI = CreateMemTemp(I->Ty, ArgInfo.getIndirectAlign()); + Address AI = CreateMemTemp(I->Ty, ArgInfo.getIndirectAlign(), + "byval-temp", false); IRCallArgs[FirstIRArg] = AI.getPointer(); EmitAggregateCopy(AI, Addr, I->Ty, RV.isVolatileQualified()); } else { @@ -3350,6 +3910,25 @@ else V = Builder.CreateLoad(RV.getAggregateAddress()); + // Implement swifterror by copying into a new swifterror argument. + // We'll write back in the normal path out of the call. + if (CallInfo.getExtParameterInfo(ArgNo).getABI() + == ParameterABI::SwiftErrorResult) { + assert(!swiftErrorTemp.isValid() && "multiple swifterror args"); + + QualType pointeeTy = I->Ty->getPointeeType(); + swiftErrorArg = + Address(V, getContext().getTypeAlignInChars(pointeeTy)); + + swiftErrorTemp = + CreateMemTemp(pointeeTy, getPointerAlign(), "swifterror.temp"); + V = swiftErrorTemp.getPointer(); + cast<llvm::AllocaInst>(V)->setSwiftError(true); + + llvm::Value *errorValue = Builder.CreateLoad(swiftErrorArg); + Builder.CreateStore(errorValue, swiftErrorTemp); + } + // We might have to widen integers, but we should never truncate. if (ArgInfo.getCoerceToType() != V->getType() && V->getType()->isIntegerTy()) @@ -3360,6 +3939,7 @@ if (FirstIRArg < IRFuncTy->getNumParams() && V->getType() != IRFuncTy->getParamType(FirstIRArg)) V = Builder.CreateBitCast(V, IRFuncTy->getParamType(FirstIRArg)); + IRCallArgs[FirstIRArg] = V; break; } @@ -3397,7 +3977,8 @@ Builder.CreateMemCpy(TempAlloca, Src, SrcSize); Src = TempAlloca; } else { - Src = Builder.CreateBitCast(Src, llvm::PointerType::getUnqual(STy)); + Src = Builder.CreateBitCast(Src, + STy->getPointerTo(Src.getAddressSpace())); } auto SrcLayout = CGM.getDataLayout().getStructLayout(STy); @@ -3418,6 +3999,51 @@ break; } + case ABIArgInfo::CoerceAndExpand: { + auto coercionType = ArgInfo.getCoerceAndExpandType(); + auto layout = CGM.getDataLayout().getStructLayout(coercionType); + + llvm::Value *tempSize = nullptr; + Address addr = Address::invalid(); + if (RV.isAggregate()) { + addr = RV.getAggregateAddress(); + } else { + assert(RV.isScalar()); // complex should always just be direct + + llvm::Type *scalarType = RV.getScalarVal()->getType(); + auto scalarSize = CGM.getDataLayout().getTypeAllocSize(scalarType); + auto scalarAlign = CGM.getDataLayout().getPrefTypeAlignment(scalarType); + + tempSize = llvm::ConstantInt::get(CGM.Int64Ty, scalarSize); + + // Materialize to a temporary. + addr = CreateTempAlloca(RV.getScalarVal()->getType(), + CharUnits::fromQuantity(std::max(layout->getAlignment(), + scalarAlign))); + EmitLifetimeStart(scalarSize, addr.getPointer()); + + Builder.CreateStore(RV.getScalarVal(), addr); + } + + addr = Builder.CreateElementBitCast(addr, coercionType); + + unsigned IRArgPos = FirstIRArg; + for (unsigned i = 0, e = coercionType->getNumElements(); i != e; ++i) { + llvm::Type *eltType = coercionType->getElementType(i); + if (ABIArgInfo::isPaddingForCoerceAndExpand(eltType)) continue; + Address eltAddr = Builder.CreateStructGEP(addr, i, layout); + llvm::Value *elt = Builder.CreateLoad(eltAddr); + IRCallArgs[IRArgPos++] = elt; + } + assert(IRArgPos == FirstIRArg + NumIRArgs); + + if (tempSize) { + EmitLifetimeEnd(tempSize, addr.getPointer()); + } + + break; + } + case ABIArgInfo::Expand: unsigned IRArgPos = FirstIRArg; ExpandTypeToArgs(I->Ty, RV, IRFuncTy, IRCallArgs, IRArgPos); @@ -3426,6 +4052,9 @@ } } + llvm::Value *CalleePtr = Callee.getFunctionPointer(); + + // If we're using inalloca, set up that argument. if (ArgMemory.isValid()) { llvm::Value *Arg = ArgMemory.getPointer(); if (CallInfo.isVariadic()) { @@ -3433,10 +4062,9 @@ // end up with a variadic prototype and an inalloca call site. In such // cases, we can't do any parameter mismatch checks. Give up and bitcast // the callee. - unsigned CalleeAS = - cast<llvm::PointerType>(Callee->getType())->getAddressSpace(); - Callee = Builder.CreateBitCast( - Callee, getTypes().GetFunctionType(CallInfo)->getPointerTo(CalleeAS)); + unsigned CalleeAS = CalleePtr->getType()->getPointerAddressSpace(); + auto FnTy = getTypes().GetFunctionType(CallInfo)->getPointerTo(CalleeAS); + CalleePtr = Builder.CreateBitCast(CalleePtr, FnTy); } else { llvm::Type *LastParamTy = IRFuncTy->getParamType(IRFuncTy->getNumParams() - 1); @@ -3459,6 +4087,7 @@ assert(IRFunctionArgs.hasInallocaArg()); IRCallArgs[IRFunctionArgs.getInallocaArgNo()] = Arg; } + #ifndef noCbC if (this->FnRetTy.getTypePtr()->is__CodeType() && CallInfo.getReturnType().getTypePtr()->is__CodeType() && ! EHStack.empty() ) { EHCleanupScope &Scope = cast<EHCleanupScope>(*EHStack.begin()); @@ -3485,39 +4114,58 @@ Fn->Emit(*this, cleanupFlags); } #endif + + // 2. Prepare the function pointer. + + // If the callee is a bitcast of a non-variadic function to have a + // variadic function pointer type, check to see if we can remove the + // bitcast. This comes up with unprototyped functions. + // + // This makes the IR nicer, but more importantly it ensures that we + // can inline the function at -O0 if it is marked always_inline. + auto simplifyVariadicCallee = [](llvm::Value *Ptr) -> llvm::Value* { + llvm::FunctionType *CalleeFT = + cast<llvm::FunctionType>(Ptr->getType()->getPointerElementType()); + if (!CalleeFT->isVarArg()) + return Ptr; + + llvm::ConstantExpr *CE = dyn_cast<llvm::ConstantExpr>(Ptr); + if (!CE || CE->getOpcode() != llvm::Instruction::BitCast) + return Ptr; + + llvm::Function *OrigFn = dyn_cast<llvm::Function>(CE->getOperand(0)); + if (!OrigFn) + return Ptr; + + llvm::FunctionType *OrigFT = OrigFn->getFunctionType(); + + // If the original type is variadic, or if any of the component types + // disagree, we cannot remove the cast. + if (OrigFT->isVarArg() || + OrigFT->getNumParams() != CalleeFT->getNumParams() || + OrigFT->getReturnType() != CalleeFT->getReturnType()) + return Ptr; + + for (unsigned i = 0, e = OrigFT->getNumParams(); i != e; ++i) + if (OrigFT->getParamType(i) != CalleeFT->getParamType(i)) + return Ptr; + + return OrigFn; + }; + CalleePtr = simplifyVariadicCallee(CalleePtr); + + // 3. Perform the actual call. + + // Deactivate any cleanups that we're supposed to do immediately before + // the call. if (!CallArgs.getCleanupsToDeactivate().empty()) deactivateArgCleanupsBeforeCall(*this, CallArgs); - // If the callee is a bitcast of a function to a varargs pointer to function - // type, check to see if we can remove the bitcast. This handles some cases - // with unprototyped functions. - if (llvm::ConstantExpr *CE = dyn_cast<llvm::ConstantExpr>(Callee)) - if (llvm::Function *CalleeF = dyn_cast<llvm::Function>(CE->getOperand(0))) { - llvm::PointerType *CurPT=cast<llvm::PointerType>(Callee->getType()); - llvm::FunctionType *CurFT = - cast<llvm::FunctionType>(CurPT->getElementType()); - llvm::FunctionType *ActualFT = CalleeF->getFunctionType(); - - if (CE->getOpcode() == llvm::Instruction::BitCast && - ActualFT->getReturnType() == CurFT->getReturnType() && - ActualFT->getNumParams() == CurFT->getNumParams() && - ActualFT->getNumParams() == IRCallArgs.size() && - (CurFT->isVarArg() || !ActualFT->isVarArg())) { - bool ArgsMatch = true; - for (unsigned i = 0, e = ActualFT->getNumParams(); i != e; ++i) - if (ActualFT->getParamType(i) != CurFT->getParamType(i)) { - ArgsMatch = false; - break; - } - - // Strip the cast if we can get away with it. This is a nice cleanup, - // but also allows us to inline the function at -O0 if it is marked - // always_inline. - if (ArgsMatch) - Callee = CalleeF; - } - } - + // Assert that the arguments we computed match up. The IR verifier + // will catch this, but this is a common enough source of problems + // during IRGen changes that it's way better for debugging to catch + // it ourselves here. +#ifndef NDEBUG assert(IRCallArgs.size() == IRFuncTy->getNumParams() || IRFuncTy->isVarArg()); for (unsigned i = 0; i < IRCallArgs.size(); ++i) { // Inalloca argument can have different type. @@ -3527,73 +4175,102 @@ if (i < IRFuncTy->getNumParams()) assert(IRCallArgs[i]->getType() == IRFuncTy->getParamType(i)); } - +#endif + + // Compute the calling convention and attributes. unsigned CallingConv; - CodeGen::AttributeListType AttributeList; - CGM.ConstructAttributeList(Callee->getName(), CallInfo, CalleeInfo, - AttributeList, CallingConv, + llvm::AttributeList Attrs; + CGM.ConstructAttributeList(CalleePtr->getName(), CallInfo, + Callee.getAbstractInfo(), Attrs, CallingConv, /*AttrOnCallSite=*/true); - llvm::AttributeSet Attrs = llvm::AttributeSet::get(getLLVMContext(), - AttributeList); - + + // Apply some call-site-specific attributes. + // TODO: work this into building the attribute set. + + // Apply always_inline to all calls within flatten functions. + // FIXME: should this really take priority over __try, below? + if (CurCodeDecl && CurCodeDecl->hasAttr<FlattenAttr>() && + !(Callee.getAbstractInfo().getCalleeDecl() && + Callee.getAbstractInfo().getCalleeDecl()->hasAttr<NoInlineAttr>())) { + Attrs = + Attrs.addAttribute(getLLVMContext(), llvm::AttributeList::FunctionIndex, + llvm::Attribute::AlwaysInline); + } + + // Disable inlining inside SEH __try blocks. + if (isSEHTryScope()) { + Attrs = + Attrs.addAttribute(getLLVMContext(), llvm::AttributeList::FunctionIndex, + llvm::Attribute::NoInline); + } + + // Decide whether to use a call or an invoke. bool CannotThrow; if (currentFunctionUsesSEHTry()) { - // SEH cares about asynchronous exceptions, everything can "throw." + // SEH cares about asynchronous exceptions, so everything can "throw." CannotThrow = false; } else if (isCleanupPadScope() && EHPersonality::get(*this).isMSVCXXPersonality()) { // The MSVC++ personality will implicitly terminate the program if an - // exception is thrown. An unwind edge cannot be reached. + // exception is thrown during a cleanup outside of a try/catch. + // We don't need to model anything in IR to get this behavior. CannotThrow = true; } else { - // Otherwise, nowunind callsites will never throw. - CannotThrow = Attrs.hasAttribute(llvm::AttributeSet::FunctionIndex, + // Otherwise, nounwind call sites will never throw. + CannotThrow = Attrs.hasAttribute(llvm::AttributeList::FunctionIndex, llvm::Attribute::NoUnwind); } llvm::BasicBlock *InvokeDest = CannotThrow ? nullptr : getInvokeDest(); SmallVector<llvm::OperandBundleDef, 1> BundleList; - getBundlesForFunclet(Callee, CurrentFuncletPad, BundleList); - + getBundlesForFunclet(CalleePtr, CurrentFuncletPad, BundleList); + + // Emit the actual call/invoke instruction. llvm::CallSite CS; if (!InvokeDest) { - CS = Builder.CreateCall(Callee, IRCallArgs, BundleList); + CS = Builder.CreateCall(CalleePtr, IRCallArgs, BundleList); } else { llvm::BasicBlock *Cont = createBasicBlock("invoke.cont"); - CS = Builder.CreateInvoke(Callee, Cont, InvokeDest, IRCallArgs, + CS = Builder.CreateInvoke(CalleePtr, Cont, InvokeDest, IRCallArgs, BundleList); EmitBlock(Cont); } + llvm::Instruction *CI = CS.getInstruction(); if (callOrInvoke) - *callOrInvoke = CS.getInstruction(); - - if (CurCodeDecl && CurCodeDecl->hasAttr<FlattenAttr>() && - !CS.hasFnAttr(llvm::Attribute::NoInline)) - Attrs = - Attrs.addAttribute(getLLVMContext(), llvm::AttributeSet::FunctionIndex, - llvm::Attribute::AlwaysInline); - - // Disable inlining inside SEH __try blocks. - if (isSEHTryScope()) - Attrs = - Attrs.addAttribute(getLLVMContext(), llvm::AttributeSet::FunctionIndex, - llvm::Attribute::NoInline); - + *callOrInvoke = CI; + + // Apply the attributes and calling convention. CS.setAttributes(Attrs); CS.setCallingConv(static_cast<llvm::CallingConv::ID>(CallingConv)); - // Insert instrumentation or attach profile metadata at indirect call sites + // Apply various metadata. + + if (!CI->getType()->isVoidTy()) + CI->setName("call"); + + // Insert instrumentation or attach profile metadata at indirect call sites. + // For more details, see the comment before the definition of + // IPVK_IndirectCallTarget in InstrProfData.inc. if (!CS.getCalledFunction()) PGO.valueProfile(Builder, llvm::IPVK_IndirectCallTarget, - CS.getInstruction(), Callee); + CI, CalleePtr); // In ObjC ARC mode with no ObjC ARC exception safety, tell the ARC // optimizer it can aggressively ignore unwind edges. if (CGM.getLangOpts().ObjCAutoRefCount) - AddObjCARCExceptionMetadata(CS.getInstruction()); + AddObjCARCExceptionMetadata(CI); + + // Suppress tail calls if requested. + if (llvm::CallInst *Call = dyn_cast<llvm::CallInst>(CI)) { + const Decl *TargetDecl = Callee.getAbstractInfo().getCalleeDecl(); + if (TargetDecl && TargetDecl->hasAttr<NotTailCalledAttr>()) + Call->setTailCallKind(llvm::CallInst::TCK_NoTail); + } + + // 4. Finish the call. // If the call doesn't return, finish the basic block and clear the - // insertion point; this allows the rest of IRgen to discard + // insertion point; this allows the rest of IRGen to discard // unreachable code. if (CS.doesNotReturn()) { if (UnusedReturnSize) @@ -3612,12 +4289,14 @@ return GetUndefRValue(RetTy); } - llvm::Instruction *CI = CS.getInstruction(); - if (Builder.isNamePreserving() && !CI->getType()->isVoidTy()) - CI->setName("call"); - - // Emit any writebacks immediately. Arguably this should happen - // after any return-value munging. + // Perform the swifterror writeback. + if (swiftErrorTemp.isValid()) { + llvm::Value *errorResult = Builder.CreateLoad(swiftErrorTemp); + Builder.CreateStore(errorResult, swiftErrorArg); + } + + // Emit any call-associated writebacks immediately. Arguably this + // should happen after any return-value munging. if (CallArgs.hasWritebacks()) emitWritebacks(*this, CallArgs); @@ -3625,14 +4304,35 @@ // lexical order, so deactivate it and run it manually here. CallArgs.freeArgumentMemory(*this); - if (llvm::CallInst *Call = dyn_cast<llvm::CallInst>(CI)) { - const Decl *TargetDecl = CalleeInfo.getCalleeDecl(); - if (TargetDecl && TargetDecl->hasAttr<NotTailCalledAttr>()) - Call->setTailCallKind(llvm::CallInst::TCK_NoTail); - } - + // Extract the return value. RValue Ret = [&] { switch (RetAI.getKind()) { + case ABIArgInfo::CoerceAndExpand: { + auto coercionType = RetAI.getCoerceAndExpandType(); + auto layout = CGM.getDataLayout().getStructLayout(coercionType); + + Address addr = SRetPtr; + addr = Builder.CreateElementBitCast(addr, coercionType); + + assert(CI->getType() == RetAI.getUnpaddedCoerceAndExpandType()); + bool requiresExtract = isa<llvm::StructType>(CI->getType()); + + unsigned unpaddedIndex = 0; + for (unsigned i = 0, e = coercionType->getNumElements(); i != e; ++i) { + llvm::Type *eltType = coercionType->getElementType(i); + if (ABIArgInfo::isPaddingForCoerceAndExpand(eltType)) continue; + Address eltAddr = Builder.CreateStructGEP(addr, i, layout); + llvm::Value *elt = CI; + if (requiresExtract) + elt = Builder.CreateExtractValue(elt, unpaddedIndex++); + else + assert(unpaddedIndex == 0); + Builder.CreateStore(elt, eltAddr); + } + // FALLTHROUGH + LLVM_FALLTHROUGH; + } + case ABIArgInfo::InAlloca: case ABIArgInfo::Indirect: { RValue ret = convertTempToRValue(SRetPtr, RetTy, SourceLocation()); @@ -3702,8 +4402,8 @@ llvm_unreachable("Unhandled ABIArgInfo::Kind"); } (); - const Decl *TargetDecl = CalleeInfo.getCalleeDecl(); - + // Emit the assume_aligned check on the return value. + const Decl *TargetDecl = Callee.getAbstractInfo().getCalleeDecl(); if (Ret.isScalar() && TargetDecl) { if (const auto *AA = TargetDecl->getAttr<AssumeAlignedAttr>()) { llvm::Value *OffsetValue = nullptr; @@ -3714,6 +4414,10 @@ llvm::ConstantInt *AlignmentCI = cast<llvm::ConstantInt>(Alignment); EmitAlignmentAssumption(Ret.getScalarVal(), AlignmentCI->getZExtValue(), OffsetValue); + } else if (const auto *AA = TargetDecl->getAttr<AllocAlignAttr>()) { + llvm::Value *ParamVal = + CallArgs[AA->getParamIndex() - 1].RV.getScalarVal(); + EmitAlignmentAssumption(Ret.getScalarVal(), ParamVal); } }
--- a/tools/clang/lib/Driver/Types.cpp Wed Dec 06 14:37:17 2017 +0900 +++ b/tools/clang/lib/Driver/Types.cpp Tue Dec 12 19:42:58 2017 +0900 @@ -44,13 +44,28 @@ return getInfo(Id).PreprocessedType; } +types::ID types::getPrecompiledType(ID Id) { + if (strchr(getInfo(Id).Flags, 'm')) + return TY_ModuleFile; + if (onlyPrecompileType(Id)) + return TY_PCH; + return TY_INVALID; +} + const char *types::getTypeTempSuffix(ID Id, bool CLMode) { - if (Id == TY_Object && CLMode) - return "obj"; - if (Id == TY_Image && CLMode) - return "exe"; - if (Id == TY_PP_Asm && CLMode) - return "asm"; + if (CLMode) { + switch (Id) { + case TY_Object: + case TY_LTO_BC: + return "obj"; + case TY_Image: + return "exe"; + case TY_PP_Asm: + return "asm"; + default: + break; + } + } return getInfo(Id).TempSuffix; } @@ -95,6 +110,7 @@ case TY_ObjCHeader: case TY_PP_ObjCHeader: case TY_CXXHeader: case TY_PP_CXXHeader: case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader: + case TY_CXXModule: case TY_PP_CXXModule: case TY_AST: case TY_ModuleFile: case TY_LLVM_IR: case TY_LLVM_BC: return true; @@ -123,6 +139,7 @@ case TY_ObjCXX: case TY_PP_ObjCXX: case TY_PP_ObjCXX_Alias: case TY_CXXHeader: case TY_PP_CXXHeader: case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader: + case TY_CXXModule: case TY_PP_CXXModule: case TY_CUDA: case TY_PP_CUDA: case TY_CUDA_DEVICE: return true; } @@ -153,54 +170,67 @@ } } -types::ID types::lookupTypeForExtension(const char *Ext) { +bool types::isSrcFile(ID Id) { + return Id != TY_Object && getPreprocessedType(Id) != TY_INVALID; +} + +types::ID types::lookupTypeForExtension(llvm::StringRef Ext) { return llvm::StringSwitch<types::ID>(Ext) .Case("c", TY_C) + .Case("C", TY_CXX) + .Case("F", TY_Fortran) + .Case("f", TY_PP_Fortran) + .Case("h", TY_CHeader) + .Case("H", TY_CXXHeader) .Case("i", TY_PP_C) .Case("m", TY_ObjC) .Case("M", TY_ObjCXX) - .Case("h", TY_CHeader) - .Case("C", TY_CXX) - .Case("H", TY_CXXHeader) - .Case("f", TY_PP_Fortran) - .Case("F", TY_Fortran) + .Case("o", TY_Object) + .Case("S", TY_Asm) .Case("s", TY_PP_Asm) - .Case("asm", TY_PP_Asm) - .Case("S", TY_Asm) - .Case("o", TY_Object) - .Case("obj", TY_Object) - .Case("lib", TY_Object) - .Case("ii", TY_PP_CXX) - .Case("mi", TY_PP_ObjC) - .Case("mm", TY_ObjCXX) .Case("bc", TY_LLVM_BC) .Case("cc", TY_CXX) .Case("CC", TY_CXX) .Case("cl", TY_CL) .Case("cp", TY_CXX) .Case("cu", TY_CUDA) - .Case("cui", TY_PP_CUDA) .Case("hh", TY_CXXHeader) + .Case("ii", TY_PP_CXX) .Case("ll", TY_LLVM_IR) - .Case("hpp", TY_CXXHeader) + .Case("mi", TY_PP_ObjC) + .Case("mm", TY_ObjCXX) + .Case("rs", TY_RenderScript) + .Case("adb", TY_Ada) .Case("ads", TY_Ada) - .Case("adb", TY_Ada) + .Case("asm", TY_PP_Asm) .Case("ast", TY_AST) + .Case("ccm", TY_CXXModule) + .Case("cpp", TY_CXX) + .Case("CPP", TY_CXX) .Case("c++", TY_CXX) .Case("C++", TY_CXX) + .Case("cui", TY_PP_CUDA) .Case("cxx", TY_CXX) - .Case("cpp", TY_CXX) - .Case("CPP", TY_CXX) .Case("CXX", TY_CXX) + .Case("F90", TY_Fortran) + .Case("f90", TY_PP_Fortran) + .Case("F95", TY_Fortran) + .Case("f95", TY_PP_Fortran) .Case("for", TY_PP_Fortran) .Case("FOR", TY_PP_Fortran) .Case("fpp", TY_Fortran) .Case("FPP", TY_Fortran) - .Case("f90", TY_PP_Fortran) - .Case("f95", TY_PP_Fortran) - .Case("F90", TY_Fortran) - .Case("F95", TY_Fortran) + .Case("gch", TY_PCH) + .Case("hpp", TY_CXXHeader) + .Case("iim", TY_PP_CXXModule) + .Case("lib", TY_Object) .Case("mii", TY_PP_ObjCXX) + .Case("obj", TY_Object) + .Case("pch", TY_PCH) + .Case("pcm", TY_ModuleFile) + .Case("c++m", TY_CXXModule) + .Case("cppm", TY_CXXModule) + .Case("cxxm", TY_CXXModule) .Case("pcm", TY_ModuleFile) #ifndef noCbC .Case("cbc", TY_C) @@ -226,9 +256,11 @@ P.push_back(phases::Preprocess); } - if (onlyPrecompileType(Id)) { + if (getPrecompiledType(Id) != TY_INVALID) { P.push_back(phases::Precompile); - } else { + } + + if (!onlyPrecompileType(Id)) { if (!onlyAssembleType(Id)) { P.push_back(phases::Compile); P.push_back(phases::Backend); @@ -237,12 +269,11 @@ } } - if (!onlyPrecompileType(Id) && Id != TY_CUDA_DEVICE) { + if (!onlyPrecompileType(Id)) { P.push_back(phases::Link); } assert(0 < P.size() && "Not enough phases in list"); assert(P.size() <= phases::MaxNumberOfPhases && "Too many phases in list"); - return; } ID types::lookupCXXTypeForCType(ID Id) { @@ -260,3 +291,21 @@ return types::TY_PP_CXXHeader; } } + +ID types::lookupHeaderTypeForSourceType(ID Id) { + switch (Id) { + default: + return Id; + + case types::TY_C: + return types::TY_CHeader; + case types::TY_CXX: + return types::TY_CXXHeader; + case types::TY_ObjC: + return types::TY_ObjCHeader; + case types::TY_ObjCXX: + return types::TY_ObjCXXHeader; + case types::TY_CL: + return types::TY_CLHeader; + } +}
--- a/tools/clang/lib/Frontend/CompilerInvocation.cpp Wed Dec 06 14:37:17 2017 +0900 +++ b/tools/clang/lib/Frontend/CompilerInvocation.cpp Tue Dec 12 19:42:58 2017 +0900 @@ -7,6 +7,7 @@ // //===----------------------------------------------------------------------===// +#include "clang/Frontend/CompilerInvocation.h" #include "TestModuleFileExtension.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/FileManager.h" @@ -15,11 +16,11 @@ #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Options.h" #include "clang/Driver/Util.h" -#include "clang/Frontend/CompilerInvocation.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Frontend/LangStandard.h" #include "clang/Frontend/Utils.h" #include "clang/Lex/HeaderSearchOptions.h" +#include "clang/Lex/PreprocessorOptions.h" #include "clang/Serialization/ASTReader.h" #include "clang/Serialization/ModuleFileExtension.h" #include "llvm/ADT/Hashing.h" @@ -33,6 +34,7 @@ #include "llvm/Option/ArgList.h" #include "llvm/Option/OptTable.h" #include "llvm/Option/Option.h" +#include "llvm/ProfileData/InstrProfReader.h" #include "llvm/Support/CodeGen.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" @@ -40,6 +42,7 @@ #include "llvm/Support/Path.h" #include "llvm/Support/Process.h" #include "llvm/Target/TargetOptions.h" +#include "llvm/Support/ScopedPrinter.h" #include <atomic> #include <memory> #include <sys/stat.h> @@ -57,12 +60,11 @@ PreprocessorOpts(new PreprocessorOptions()) {} CompilerInvocationBase::CompilerInvocationBase(const CompilerInvocationBase &X) - : RefCountedBase<CompilerInvocation>(), - LangOpts(new LangOptions(*X.getLangOpts())), - TargetOpts(new TargetOptions(X.getTargetOpts())), - DiagnosticOpts(new DiagnosticOptions(X.getDiagnosticOpts())), - HeaderSearchOpts(new HeaderSearchOptions(X.getHeaderSearchOpts())), - PreprocessorOpts(new PreprocessorOptions(X.getPreprocessorOpts())) {} + : LangOpts(new LangOptions(*X.getLangOpts())), + TargetOpts(new TargetOptions(X.getTargetOpts())), + DiagnosticOpts(new DiagnosticOptions(X.getDiagnosticOpts())), + HeaderSearchOpts(new HeaderSearchOptions(X.getHeaderSearchOpts())), + PreprocessorOpts(new PreprocessorOptions(X.getPreprocessorOpts())) {} CompilerInvocationBase::~CompilerInvocationBase() {} @@ -79,7 +81,7 @@ static unsigned getOptimizationLevel(ArgList &Args, InputKind IK, DiagnosticsEngine &Diags) { unsigned DefaultOpt = 0; - if (IK == IK_OpenCL && !Args.hasArg(OPT_cl_opt_disable)) + if (IK.getLanguage() == InputKind::OpenCL && !Args.hasArg(OPT_cl_opt_disable)) DefaultOpt = 2; if (Arg *A = Args.getLastArg(options::OPT_O_Group)) { @@ -95,6 +97,9 @@ if (S == "s" || S == "z" || S.empty()) return 2; + if (S == "g") + return 1; + return getLastArgIntValue(Args, OPT_O, DefaultOpt, Diags); } @@ -235,6 +240,7 @@ } Opts.ShowCheckerHelp = Args.hasArg(OPT_analyzer_checker_help); + Opts.ShowEnabledCheckerList = Args.hasArg(OPT_analyzer_list_enabled_checkers); Opts.DisableAllChecks = Args.hasArg(OPT_analyzer_disable_all_checks); Opts.visualizeExplodedGraphWithGraphViz = @@ -324,6 +330,17 @@ return "default"; } +static StringRef getRelocModel(ArgList &Args, DiagnosticsEngine &Diags) { + if (Arg *A = Args.getLastArg(OPT_mrelocation_model)) { + StringRef Value = A->getValue(); + if (Value == "static" || Value == "pic" || Value == "ropi" || + Value == "rwpi" || Value == "ropi-rwpi" || Value == "dynamic-no-pic") + return Value; + Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Value; + } + return "pic"; +} + /// \brief Create a new Regex instance out of the string value in \p RpassArg. /// It returns a pointer to the newly generated Regex instance. static std::shared_ptr<llvm::Regex> @@ -375,6 +392,46 @@ } } +// Set the profile kind for fprofile-instrument. +static void setPGOInstrumentor(CodeGenOptions &Opts, ArgList &Args, + DiagnosticsEngine &Diags) { + Arg *A = Args.getLastArg(OPT_fprofile_instrument_EQ); + if (A == nullptr) + return; + StringRef S = A->getValue(); + unsigned I = llvm::StringSwitch<unsigned>(S) + .Case("none", CodeGenOptions::ProfileNone) + .Case("clang", CodeGenOptions::ProfileClangInstr) + .Case("llvm", CodeGenOptions::ProfileIRInstr) + .Default(~0U); + if (I == ~0U) { + Diags.Report(diag::err_drv_invalid_pgo_instrumentor) << A->getAsString(Args) + << S; + return; + } + CodeGenOptions::ProfileInstrKind Instrumentor = + static_cast<CodeGenOptions::ProfileInstrKind>(I); + Opts.setProfileInstr(Instrumentor); +} + +// Set the profile kind using fprofile-instrument-use-path. +static void setPGOUseInstrumentor(CodeGenOptions &Opts, + const Twine &ProfileName) { + auto ReaderOrErr = llvm::IndexedInstrProfReader::create(ProfileName); + // In error, return silently and let Clang PGOUse report the error message. + if (auto E = ReaderOrErr.takeError()) { + llvm::consumeError(std::move(E)); + Opts.setProfileUse(CodeGenOptions::ProfileClangInstr); + return; + } + std::unique_ptr<llvm::IndexedInstrProfReader> PGOReader = + std::move(ReaderOrErr.get()); + if (PGOReader->isIRLevelProfile()) + Opts.setProfileUse(CodeGenOptions::ProfileIRInstr); + else + Opts.setProfileUse(CodeGenOptions::ProfileClangInstr); +} + static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, DiagnosticsEngine &Diags, const TargetOptions &TargetOpts) { @@ -394,19 +451,41 @@ } Opts.OptimizationLevel = OptimizationLevel; - // We must always run at least the always inlining pass. - Opts.setInlining( - (Opts.OptimizationLevel > 1) ? CodeGenOptions::NormalInlining - : CodeGenOptions::OnlyAlwaysInlining); - // -fno-inline-functions overrides OptimizationLevel > 1. - Opts.NoInline = Args.hasArg(OPT_fno_inline); - Opts.setInlining(Args.hasArg(OPT_fno_inline_functions) ? - CodeGenOptions::OnlyAlwaysInlining : Opts.getInlining()); + // At O0 we want to fully disable inlining outside of cases marked with + // 'alwaysinline' that are required for correctness. + Opts.setInlining((Opts.OptimizationLevel == 0) + ? CodeGenOptions::OnlyAlwaysInlining + : CodeGenOptions::NormalInlining); + // Explicit inlining flags can disable some or all inlining even at + // optimization levels above zero. + if (Arg *InlineArg = Args.getLastArg( + options::OPT_finline_functions, options::OPT_finline_hint_functions, + options::OPT_fno_inline_functions, options::OPT_fno_inline)) { + if (Opts.OptimizationLevel > 0) { + const Option &InlineOpt = InlineArg->getOption(); + if (InlineOpt.matches(options::OPT_finline_functions)) + Opts.setInlining(CodeGenOptions::NormalInlining); + else if (InlineOpt.matches(options::OPT_finline_hint_functions)) + Opts.setInlining(CodeGenOptions::OnlyHintInlining); + else + Opts.setInlining(CodeGenOptions::OnlyAlwaysInlining); + } + } + + Opts.ExperimentalNewPassManager = Args.hasFlag( + OPT_fexperimental_new_pass_manager, OPT_fno_experimental_new_pass_manager, + /* Default */ false); + + Opts.DebugPassManager = + Args.hasFlag(OPT_fdebug_pass_manager, OPT_fno_debug_pass_manager, + /* Default */ false); if (Arg *A = Args.getLastArg(OPT_fveclib)) { StringRef Name = A->getValue(); if (Name == "Accelerate") Opts.setVecLib(CodeGenOptions::Accelerate); + else if (Name == "SVML") + Opts.setVecLib(CodeGenOptions::SVML); else if (Name == "none") Opts.setVecLib(CodeGenOptions::NoLibrary); else @@ -416,34 +495,40 @@ if (Arg *A = Args.getLastArg(OPT_debug_info_kind_EQ)) { unsigned Val = llvm::StringSwitch<unsigned>(A->getValue()) - .Case("line-tables-only", CodeGenOptions::DebugLineTablesOnly) - .Case("limited", CodeGenOptions::LimitedDebugInfo) - .Case("standalone", CodeGenOptions::FullDebugInfo) + .Case("line-tables-only", codegenoptions::DebugLineTablesOnly) + .Case("limited", codegenoptions::LimitedDebugInfo) + .Case("standalone", codegenoptions::FullDebugInfo) .Default(~0U); if (Val == ~0U) Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << A->getValue(); else - Opts.setDebugInfo(static_cast<CodeGenOptions::DebugInfoKind>(Val)); + Opts.setDebugInfo(static_cast<codegenoptions::DebugInfoKind>(Val)); } if (Arg *A = Args.getLastArg(OPT_debugger_tuning_EQ)) { unsigned Val = llvm::StringSwitch<unsigned>(A->getValue()) - .Case("gdb", CodeGenOptions::DebuggerKindGDB) - .Case("lldb", CodeGenOptions::DebuggerKindLLDB) - .Case("sce", CodeGenOptions::DebuggerKindSCE) + .Case("gdb", unsigned(llvm::DebuggerKind::GDB)) + .Case("lldb", unsigned(llvm::DebuggerKind::LLDB)) + .Case("sce", unsigned(llvm::DebuggerKind::SCE)) .Default(~0U); if (Val == ~0U) Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << A->getValue(); else - Opts.setDebuggerTuning(static_cast<CodeGenOptions::DebuggerKind>(Val)); + Opts.setDebuggerTuning(static_cast<llvm::DebuggerKind>(Val)); } Opts.DwarfVersion = getLastArgIntValue(Args, OPT_dwarf_version_EQ, 0, Diags); Opts.DebugColumnInfo = Args.hasArg(OPT_dwarf_column_info); Opts.EmitCodeView = Args.hasArg(OPT_gcodeview); + Opts.MacroDebugInfo = Args.hasArg(OPT_debug_info_macro); + Opts.WholeProgramVTables = Args.hasArg(OPT_fwhole_program_vtables); + Opts.LTOVisibilityPublicStd = Args.hasArg(OPT_flto_visibility_public_std); + Opts.EnableSplitDwarf = Args.hasArg(OPT_enable_split_dwarf); Opts.SplitDwarfFile = Args.getLastArgValue(OPT_split_dwarf_file); + Opts.SplitDwarfInlining = !Args.hasArg(OPT_fno_split_dwarf_inlining); Opts.DebugTypeExtRefs = Args.hasArg(OPT_dwarf_ext_refs); - Opts.DebugExplicitImport = Triple.isPS4CPU(); + Opts.DebugExplicitImport = Args.hasArg(OPT_dwarf_explicit_import); + Opts.DebugFwdTemplateParams = Args.hasArg(OPT_debug_forward_template_params); for (const auto &Arg : Args.getAllArgValues(OPT_fdebug_prefix_map_EQ)) Opts.DebugPrefixMap.insert(StringRef(Arg).split('=')); @@ -452,14 +537,18 @@ Args.getLastArg(OPT_emit_llvm_uselists, OPT_no_emit_llvm_uselists)) Opts.EmitLLVMUseLists = A->getOption().getID() == OPT_emit_llvm_uselists; - Opts.DisableLLVMOpts = Args.hasArg(OPT_disable_llvm_optzns); Opts.DisableLLVMPasses = Args.hasArg(OPT_disable_llvm_passes); + Opts.DisableLifetimeMarkers = Args.hasArg(OPT_disable_lifetimemarkers); + Opts.DisableO0ImplyOptNone = Args.hasArg(OPT_disable_O0_optnone); Opts.DisableRedZone = Args.hasArg(OPT_disable_red_zone); Opts.ForbidGuardVariables = Args.hasArg(OPT_fforbid_guard_variables); Opts.UseRegisterSizedBitfieldAccess = Args.hasArg( OPT_fuse_register_sized_bitfield_access); Opts.RelaxedAliasing = Args.hasArg(OPT_relaxed_aliasing); Opts.StructPathTBAA = !Args.hasArg(OPT_no_struct_path_tbaa); + Opts.FineGrainedBitfieldAccesses = + Args.hasFlag(OPT_ffine_grained_bitfield_accesses, + OPT_fno_fine_grained_bitfield_accesses, false); Opts.DwarfDebugFlags = Args.getLastArgValue(OPT_dwarf_debug_flags); Opts.MergeAllConstants = !Args.hasArg(OPT_fno_merge_all_constants); Opts.NoCommon = Args.hasArg(OPT_fno_common); @@ -471,20 +560,57 @@ getAllNoBuiltinFuncValues(Args, Opts.NoBuiltinFuncs); Opts.UnrollLoops = Args.hasFlag(OPT_funroll_loops, OPT_fno_unroll_loops, - (Opts.OptimizationLevel > 1 && !Opts.OptimizeSize)); + (Opts.OptimizationLevel > 1)); Opts.RerollLoops = Args.hasArg(OPT_freroll_loops); Opts.DisableIntegratedAS = Args.hasArg(OPT_fno_integrated_as); Opts.Autolink = !Args.hasArg(OPT_fno_autolink); Opts.SampleProfileFile = Args.getLastArgValue(OPT_fprofile_sample_use_EQ); - Opts.ProfileInstrGenerate = Args.hasArg(OPT_fprofile_instr_generate) || - Args.hasArg(OPT_fprofile_instr_generate_EQ); - Opts.InstrProfileOutput = Args.getLastArgValue(OPT_fprofile_instr_generate_EQ); - Opts.InstrProfileInput = Args.getLastArgValue(OPT_fprofile_instr_use_EQ); + Opts.DebugInfoForProfiling = Args.hasFlag( + OPT_fdebug_info_for_profiling, OPT_fno_debug_info_for_profiling, false); + Opts.GnuPubnames = Args.hasArg(OPT_ggnu_pubnames); + + setPGOInstrumentor(Opts, Args, Diags); + Opts.InstrProfileOutput = + Args.getLastArgValue(OPT_fprofile_instrument_path_EQ); + Opts.ProfileInstrumentUsePath = + Args.getLastArgValue(OPT_fprofile_instrument_use_path_EQ); + if (!Opts.ProfileInstrumentUsePath.empty()) + setPGOUseInstrumentor(Opts, Opts.ProfileInstrumentUsePath); + + if (Arg *A = Args.getLastArg(OPT_fclang_abi_compat_EQ)) { + Opts.setClangABICompat(CodeGenOptions::ClangABI::Latest); + + StringRef Ver = A->getValue(); + std::pair<StringRef, StringRef> VerParts = Ver.split('.'); + unsigned Major, Minor = 0; + + // Check the version number is valid: either 3.x (0 <= x <= 9) or + // y or y.0 (4 <= y <= current version). + if (!VerParts.first.startswith("0") && + !VerParts.first.getAsInteger(10, Major) && + 3 <= Major && Major <= CLANG_VERSION_MAJOR && + (Major == 3 ? VerParts.second.size() == 1 && + !VerParts.second.getAsInteger(10, Minor) + : VerParts.first.size() == Ver.size() || + VerParts.second == "0")) { + // Got a valid version number. + if (Major == 3 && Minor <= 8) + Opts.setClangABICompat(CodeGenOptions::ClangABI::Ver3_8); + else if (Major <= 4) + Opts.setClangABICompat(CodeGenOptions::ClangABI::Ver4); + } else if (Ver != "latest") { + Diags.Report(diag::err_drv_invalid_value) + << A->getAsString(Args) << A->getValue(); + } + } + Opts.CoverageMapping = Args.hasFlag(OPT_fcoverage_mapping, OPT_fno_coverage_mapping, false); Opts.DumpCoverageMapping = Args.hasArg(OPT_dump_coverage_mapping); Opts.AsmVerbose = Args.hasArg(OPT_masm_verbose); + Opts.PreserveAsmComments = !Args.hasArg(OPT_fno_preserve_as_comments); + Opts.AssumeSaneOperatorNew = !Args.hasArg(OPT_fno_assume_sane_operator_new); Opts.ObjCAutoRefCountExceptions = Args.hasArg(OPT_fobjc_arc_exceptions); Opts.CXAAtExit = !Args.hasArg(OPT_fno_use_cxa_atexit); Opts.CXXCtorDtorAliases = Args.hasArg(OPT_mconstructor_aliases); @@ -493,23 +619,12 @@ Opts.DisableFPElim = (Args.hasArg(OPT_mdisable_fp_elim) || Args.hasArg(OPT_pg)); Opts.DisableFree = Args.hasArg(OPT_disable_free); + Opts.DiscardValueNames = Args.hasArg(OPT_discard_value_names); Opts.DisableTailCalls = Args.hasArg(OPT_mdisable_tail_calls); Opts.FloatABI = Args.getLastArgValue(OPT_mfloat_abi); - if (Arg *A = Args.getLastArg(OPT_meabi)) { - StringRef Value = A->getValue(); - llvm::EABI EABIVersion = llvm::StringSwitch<llvm::EABI>(Value) - .Case("default", llvm::EABI::Default) - .Case("4", llvm::EABI::EABI4) - .Case("5", llvm::EABI::EABI5) - .Case("gnu", llvm::EABI::GNU) - .Default(llvm::EABI::Unknown); - if (EABIVersion == llvm::EABI::Unknown) - Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) - << Value; - else - Opts.EABIVersion = Value; - } - Opts.LessPreciseFPMAD = Args.hasArg(OPT_cl_mad_enable); + Opts.LessPreciseFPMAD = Args.hasArg(OPT_cl_mad_enable) || + Args.hasArg(OPT_cl_unsafe_math_optimizations) || + Args.hasArg(OPT_cl_fast_relaxed_math); Opts.LimitFloatPrecision = Args.getLastArgValue(OPT_mlimit_float_precision); Opts.NoInfsFPMath = (Args.hasArg(OPT_menable_no_infinities) || Args.hasArg(OPT_cl_finite_math_only) || @@ -518,8 +633,15 @@ Args.hasArg(OPT_cl_unsafe_math_optimizations) || Args.hasArg(OPT_cl_finite_math_only) || Args.hasArg(OPT_cl_fast_relaxed_math)); - Opts.NoSignedZeros = Args.hasArg(OPT_fno_signed_zeros); + Opts.NoSignedZeros = (Args.hasArg(OPT_fno_signed_zeros) || + Args.hasArg(OPT_cl_no_signed_zeros) || + Args.hasArg(OPT_cl_unsafe_math_optimizations) || + Args.hasArg(OPT_cl_fast_relaxed_math)); + Opts.FlushDenorm = Args.hasArg(OPT_cl_denorms_are_zero); + Opts.CorrectlyRoundedDivSqrt = + Args.hasArg(OPT_cl_fp32_correctly_rounded_divide_sqrt); Opts.ReciprocalMath = Args.hasArg(OPT_freciprocal_math); + Opts.NoTrappingMath = Args.hasArg(OPT_fno_trapping_math); Opts.NoZeroInitializedInBSS = Args.hasArg(OPT_mno_zero_initialized_in_bss); Opts.BackendOptions = Args.getAllArgValues(OPT_backend_option); Opts.NumRegisterParameters = getLastArgIntValue(Args, OPT_mregparm, 0, Diags); @@ -529,17 +651,20 @@ Opts.RelaxAll = Args.hasArg(OPT_mrelax_all); Opts.IncrementalLinkerCompatible = Args.hasArg(OPT_mincremental_linker_compatible); + Opts.PIECopyRelocations = + Args.hasArg(OPT_mpie_copy_relocations); Opts.OmitLeafFramePointer = Args.hasArg(OPT_momit_leaf_frame_pointer); Opts.SaveTempLabels = Args.hasArg(OPT_msave_temp_labels); Opts.NoDwarfDirectoryAsm = Args.hasArg(OPT_fno_dwarf_directory_asm); Opts.SoftFloat = Args.hasArg(OPT_msoft_float); Opts.StrictEnums = Args.hasArg(OPT_fstrict_enums); + Opts.StrictReturn = !Args.hasArg(OPT_fno_strict_return); Opts.StrictVTablePointers = Args.hasArg(OPT_fstrict_vtable_pointers); Opts.UnsafeFPMath = Args.hasArg(OPT_menable_unsafe_fp_math) || Args.hasArg(OPT_cl_unsafe_math_optimizations) || Args.hasArg(OPT_cl_fast_relaxed_math); Opts.UnwindTables = Args.hasArg(OPT_munwind_tables); - Opts.RelocationModel = Args.getLastArgValue(OPT_mrelocation_model, "pic"); + Opts.RelocationModel = getRelocModel(Args, Diags); Opts.ThreadModel = Args.getLastArgValue(OPT_mthread_model, "posix"); if (Opts.ThreadModel != "posix" && Opts.ThreadModel != "single") Diags.Report(diag::err_drv_invalid_value) @@ -557,19 +682,30 @@ Opts.MergeFunctions = Args.hasArg(OPT_fmerge_functions); + Opts.NoUseJumpTables = Args.hasArg(OPT_fno_jump_tables); + + Opts.ProfileSampleAccurate = Args.hasArg(OPT_fprofile_sample_accurate); + Opts.PrepareForLTO = Args.hasArg(OPT_flto, OPT_flto_EQ); - const Arg *A = Args.getLastArg(OPT_flto, OPT_flto_EQ); - Opts.EmitFunctionSummary = A && A->containsValue("thin"); + Opts.EmitSummaryIndex = false; + if (Arg *A = Args.getLastArg(OPT_flto_EQ)) { + StringRef S = A->getValue(); + if (S == "thin") + Opts.EmitSummaryIndex = true; + else if (S != "full") + Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << S; + } + Opts.LTOUnit = Args.hasFlag(OPT_flto_unit, OPT_fno_lto_unit, false); if (Arg *A = Args.getLastArg(OPT_fthinlto_index_EQ)) { - if (IK != IK_LLVM_IR) + if (IK.getLanguage() != InputKind::LLVM_IR) Diags.Report(diag::err_drv_argument_only_allowed_with) << A->getAsString(Args) << "-x ir"; Opts.ThinLTOIndexFile = Args.getLastArgValue(OPT_fthinlto_index_EQ); } + Opts.ThinLinkBitcodeFile = Args.getLastArgValue(OPT_fthin_link_bitcode_EQ); Opts.MSVolatile = Args.hasArg(OPT_fms_volatile); - Opts.VectorizeBB = Args.hasArg(OPT_vectorize_slp_aggressive); Opts.VectorizeLoop = Args.hasArg(OPT_vectorize_loops); Opts.VectorizeSLP = Args.hasArg(OPT_vectorize_slp); @@ -580,7 +716,8 @@ Opts.EmitGcovArcs = Args.hasArg(OPT_femit_coverage_data); Opts.EmitGcovNotes = Args.hasArg(OPT_femit_coverage_notes); if (Opts.EmitGcovArcs || Opts.EmitGcovNotes) { - Opts.CoverageFile = Args.getLastArgValue(OPT_coverage_file); + Opts.CoverageDataFile = Args.getLastArgValue(OPT_coverage_data_file); + Opts.CoverageNotesFile = Args.getLastArgValue(OPT_coverage_notes_file); Opts.CoverageExtraChecksum = Args.hasArg(OPT_coverage_cfg_checksum); Opts.CoverageNoFunctionNamesInData = Args.hasArg(OPT_coverage_no_function_names_in_data); @@ -597,18 +734,83 @@ } } } + // Handle -fembed-bitcode option. + if (Arg *A = Args.getLastArg(OPT_fembed_bitcode_EQ)) { + StringRef Name = A->getValue(); + unsigned Model = llvm::StringSwitch<unsigned>(Name) + .Case("off", CodeGenOptions::Embed_Off) + .Case("all", CodeGenOptions::Embed_All) + .Case("bitcode", CodeGenOptions::Embed_Bitcode) + .Case("marker", CodeGenOptions::Embed_Marker) + .Default(~0U); + if (Model == ~0U) { + Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name; + Success = false; + } else + Opts.setEmbedBitcode( + static_cast<CodeGenOptions::EmbedBitcodeKind>(Model)); + } + // FIXME: For backend options that are not yet recorded as function + // attributes in the IR, keep track of them so we can embed them in a + // separate data section and use them when building the bitcode. + if (Opts.getEmbedBitcode() == CodeGenOptions::Embed_All) { + for (const auto &A : Args) { + // Do not encode output and input. + if (A->getOption().getID() == options::OPT_o || + A->getOption().getID() == options::OPT_INPUT || + A->getOption().getID() == options::OPT_x || + A->getOption().getID() == options::OPT_fembed_bitcode || + (A->getOption().getGroup().isValid() && + A->getOption().getGroup().getID() == options::OPT_W_Group)) + continue; + ArgStringList ASL; + A->render(Args, ASL); + for (const auto &arg : ASL) { + StringRef ArgStr(arg); + Opts.CmdArgs.insert(Opts.CmdArgs.end(), ArgStr.begin(), ArgStr.end()); + // using \00 to seperate each commandline options. + Opts.CmdArgs.push_back('\0'); + } + } + } + Opts.PreserveVec3Type = Args.hasArg(OPT_fpreserve_vec3_type); Opts.InstrumentFunctions = Args.hasArg(OPT_finstrument_functions); + Opts.XRayInstrumentFunctions = Args.hasArg(OPT_fxray_instrument); + Opts.XRayInstructionThreshold = + getLastArgIntValue(Args, OPT_fxray_instruction_threshold_EQ, 200, Diags); Opts.InstrumentForProfiling = Args.hasArg(OPT_pg); + Opts.CallFEntry = Args.hasArg(OPT_mfentry); Opts.EmitOpenCLArgMetadata = Args.hasArg(OPT_cl_kernel_arg_info); - Opts.CompressDebugSections = Args.hasArg(OPT_compress_debug_sections); + + if (const Arg *A = Args.getLastArg(OPT_compress_debug_sections, + OPT_compress_debug_sections_EQ)) { + if (A->getOption().getID() == OPT_compress_debug_sections) { + // TODO: be more clever about the compression type auto-detection + Opts.setCompressDebugSections(llvm::DebugCompressionType::GNU); + } else { + auto DCT = llvm::StringSwitch<llvm::DebugCompressionType>(A->getValue()) + .Case("none", llvm::DebugCompressionType::None) + .Case("zlib", llvm::DebugCompressionType::Z) + .Case("zlib-gnu", llvm::DebugCompressionType::GNU) + .Default(llvm::DebugCompressionType::None); + Opts.setCompressDebugSections(DCT); + } + } + + Opts.RelaxELFRelocations = Args.hasArg(OPT_mrelax_relocations); Opts.DebugCompilationDir = Args.getLastArgValue(OPT_fdebug_compilation_dir); for (auto A : Args.filtered(OPT_mlink_bitcode_file, OPT_mlink_cuda_bitcode)) { - unsigned LinkFlags = llvm::Linker::Flags::None; - if (A->getOption().matches(OPT_mlink_cuda_bitcode)) - LinkFlags = llvm::Linker::Flags::LinkOnlyNeeded | - llvm::Linker::Flags::InternalizeLinkedSymbols; - Opts.LinkBitcodeFiles.push_back(std::make_pair(LinkFlags, A->getValue())); + CodeGenOptions::BitcodeFileToLink F; + F.Filename = A->getValue(); + if (A->getOption().matches(OPT_mlink_cuda_bitcode)) { + F.LinkFlags = llvm::Linker::Flags::LinkOnlyNeeded; + // When linking CUDA bitcode, propagate function attributes so that + // e.g. libdevice gets fast-math attrs if we're building with fast-math. + F.PropagateAttrs = true; + F.Internalize = true; + } + Opts.LinkBitcodeFiles.push_back(F); } Opts.SanitizeCoverageType = getLastArgIntValue(Args, OPT_fsanitize_coverage_type, 0, Diags); @@ -616,14 +818,35 @@ Args.hasArg(OPT_fsanitize_coverage_indirect_calls); Opts.SanitizeCoverageTraceBB = Args.hasArg(OPT_fsanitize_coverage_trace_bb); Opts.SanitizeCoverageTraceCmp = Args.hasArg(OPT_fsanitize_coverage_trace_cmp); + Opts.SanitizeCoverageTraceDiv = Args.hasArg(OPT_fsanitize_coverage_trace_div); + Opts.SanitizeCoverageTraceGep = Args.hasArg(OPT_fsanitize_coverage_trace_gep); Opts.SanitizeCoverage8bitCounters = Args.hasArg(OPT_fsanitize_coverage_8bit_counters); + Opts.SanitizeCoverageTracePC = Args.hasArg(OPT_fsanitize_coverage_trace_pc); + Opts.SanitizeCoverageTracePCGuard = + Args.hasArg(OPT_fsanitize_coverage_trace_pc_guard); + Opts.SanitizeCoverageNoPrune = Args.hasArg(OPT_fsanitize_coverage_no_prune); + Opts.SanitizeCoverageInline8bitCounters = + Args.hasArg(OPT_fsanitize_coverage_inline_8bit_counters); + Opts.SanitizeCoveragePCTable = Args.hasArg(OPT_fsanitize_coverage_pc_table); + Opts.SanitizeCoverageStackDepth = + Args.hasArg(OPT_fsanitize_coverage_stack_depth); Opts.SanitizeMemoryTrackOrigins = getLastArgIntValue(Args, OPT_fsanitize_memory_track_origins_EQ, 0, Diags); Opts.SanitizeMemoryUseAfterDtor = - Args.hasArg(OPT_fsanitize_memory_use_after_dtor); + Args.hasFlag(OPT_fsanitize_memory_use_after_dtor, + OPT_fno_sanitize_memory_use_after_dtor, + false); + Opts.SanitizeMinimalRuntime = Args.hasArg(OPT_fsanitize_minimal_runtime); Opts.SanitizeCfiCrossDso = Args.hasArg(OPT_fsanitize_cfi_cross_dso); Opts.SanitizeStats = Args.hasArg(OPT_fsanitize_stats); + if (Arg *A = Args.getLastArg(OPT_fsanitize_address_use_after_scope, + OPT_fno_sanitize_address_use_after_scope)) { + Opts.SanitizeAddressUseAfterScope = + A->getOption().getID() == OPT_fsanitize_address_use_after_scope; + } + Opts.SanitizeAddressGlobalsDeadStripping = + Args.hasArg(OPT_fsanitize_address_globals_dead_stripping); Opts.SSPBufferSize = getLastArgIntValue(Args, OPT_stack_protector_buffer_size, 8, Diags); Opts.StackRealignment = Args.hasArg(OPT_mstackrealign); @@ -676,14 +899,14 @@ } } - if (Arg *A = Args.getLastArg(OPT_ffp_contract)) { + if (Arg *A = Args.getLastArg(OPT_fdenormal_fp_math_EQ)) { StringRef Val = A->getValue(); - if (Val == "fast") - Opts.setFPContractMode(CodeGenOptions::FPC_Fast); - else if (Val == "on") - Opts.setFPContractMode(CodeGenOptions::FPC_On); - else if (Val == "off") - Opts.setFPContractMode(CodeGenOptions::FPC_Off); + if (Val == "ieee") + Opts.FPDenormalMode = "ieee"; + else if (Val == "preserve-sign") + Opts.FPDenormalMode = "preserve-sign"; + else if (Val == "positive-zero") + Opts.FPDenormalMode = "positive-zero"; else Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val; } @@ -701,6 +924,10 @@ Opts.LinkerOptions = Args.getAllArgValues(OPT_linker_option); bool NeedLocTracking = false; + Opts.OptRecordFile = Args.getLastArgValue(OPT_opt_record_file); + if (!Opts.OptRecordFile.empty()) + NeedLocTracking = true; + if (Arg *A = Args.getLastArg(OPT_Rpass_EQ)) { Opts.OptimizationRemarkPattern = GenerateOptimizationRemarkRegex(Diags, Args, A); @@ -719,16 +946,32 @@ NeedLocTracking = true; } + Opts.DiagnosticsWithHotness = + Args.hasArg(options::OPT_fdiagnostics_show_hotness); + bool UsingSampleProfile = !Opts.SampleProfileFile.empty(); + bool UsingProfile = UsingSampleProfile || + (Opts.getProfileUse() != CodeGenOptions::ProfileNone); + + if (Opts.DiagnosticsWithHotness && !UsingProfile) + Diags.Report(diag::warn_drv_diagnostics_hotness_requires_pgo) + << "-fdiagnostics-show-hotness"; + + Opts.DiagnosticsHotnessThreshold = getLastArgUInt64Value( + Args, options::OPT_fdiagnostics_hotness_threshold_EQ, 0); + if (Opts.DiagnosticsHotnessThreshold > 0 && !UsingProfile) + Diags.Report(diag::warn_drv_diagnostics_hotness_requires_pgo) + << "-fdiagnostics-hotness-threshold="; + // If the user requested to use a sample profile for PGO, then the // backend will need to track source location information so the profile // can be incorporated into the IR. - if (!Opts.SampleProfileFile.empty()) + if (UsingSampleProfile) NeedLocTracking = true; // If the user requested a flag that requires source locations available in // the backend, make sure that the backend tracks source location information. - if (NeedLocTracking && Opts.getDebugInfo() == CodeGenOptions::NoDebugInfo) - Opts.setDebugInfo(CodeGenOptions::LocTrackingOnly); + if (NeedLocTracking && Opts.getDebugInfo() == codegenoptions::NoDebugInfo) + Opts.setDebugInfo(codegenoptions::LocTrackingOnly); Opts.RewriteMapFiles = Args.getAllArgValues(OPT_frewrite_map_file); @@ -744,6 +987,11 @@ Opts.CudaGpuBinaryFileNames = Args.getAllArgValues(OPT_fcuda_include_gpubinary); + Opts.Backchain = Args.hasArg(OPT_mbackchain); + + Opts.EmitCheckPathComponentsToStrip = getLastArgIntValue( + Args, OPT_fsanitize_undefined_strip_path_components_EQ, 0, Diags); + return Success; } @@ -768,13 +1016,50 @@ // They won't be discovered by the regular preprocessor, so // we let make / ninja to know about this implicit dependency. Opts.ExtraDeps = Args.getAllArgValues(OPT_fdepfile_entry); - auto ModuleFiles = Args.getAllArgValues(OPT_fmodule_file); - Opts.ExtraDeps.insert(Opts.ExtraDeps.end(), ModuleFiles.begin(), - ModuleFiles.end()); + // Only the -fmodule-file=<file> form. + for (const Arg *A : Args.filtered(OPT_fmodule_file)) { + StringRef Val = A->getValue(); + if (Val.find('=') == StringRef::npos) + Opts.ExtraDeps.push_back(Val); + } +} + +static bool parseShowColorsArgs(const ArgList &Args, bool DefaultColor) { + // Color diagnostics default to auto ("on" if terminal supports) in the driver + // but default to off in cc1, needing an explicit OPT_fdiagnostics_color. + // Support both clang's -f[no-]color-diagnostics and gcc's + // -f[no-]diagnostics-colors[=never|always|auto]. + enum { + Colors_On, + Colors_Off, + Colors_Auto + } ShowColors = DefaultColor ? Colors_Auto : Colors_Off; + for (Arg *A : Args) { + const Option &O = A->getOption(); + if (O.matches(options::OPT_fcolor_diagnostics) || + O.matches(options::OPT_fdiagnostics_color)) { + ShowColors = Colors_On; + } else if (O.matches(options::OPT_fno_color_diagnostics) || + O.matches(options::OPT_fno_diagnostics_color)) { + ShowColors = Colors_Off; + } else if (O.matches(options::OPT_fdiagnostics_color_EQ)) { + StringRef Value(A->getValue()); + if (Value == "always") + ShowColors = Colors_On; + else if (Value == "never") + ShowColors = Colors_Off; + else if (Value == "auto") + ShowColors = Colors_Auto; + } + } + return ShowColors == Colors_On || + (ShowColors == Colors_Auto && + llvm::sys::Process::StandardErrHasColors()); } bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args, - DiagnosticsEngine *Diags) { + DiagnosticsEngine *Diags, + bool DefaultDiagColor, bool DefaultShowOpt) { using namespace options; bool Success = true; @@ -787,13 +1072,16 @@ Opts.Pedantic = Args.hasArg(OPT_pedantic); Opts.PedanticErrors = Args.hasArg(OPT_pedantic_errors); Opts.ShowCarets = !Args.hasArg(OPT_fno_caret_diagnostics); - Opts.ShowColors = Args.hasArg(OPT_fcolor_diagnostics); + Opts.ShowColors = parseShowColorsArgs(Args, DefaultDiagColor); Opts.ShowColumn = Args.hasFlag(OPT_fshow_column, OPT_fno_show_column, /*Default=*/true); Opts.ShowFixits = !Args.hasArg(OPT_fno_diagnostics_fixit_info); Opts.ShowLocation = !Args.hasArg(OPT_fno_show_source_location); - Opts.ShowOptionNames = Args.hasArg(OPT_fdiagnostics_show_option); + Opts.AbsolutePath = Args.hasArg(OPT_fdiagnostics_absolute_paths); + Opts.ShowOptionNames = + Args.hasFlag(OPT_fdiagnostics_show_option, + OPT_fno_diagnostics_show_option, DefaultShowOpt); llvm::sys::Process::UseANSIEscapeCodes(Args.hasArg(OPT_fansi_escape_codes)); @@ -879,6 +1167,9 @@ Opts.SpellCheckingLimit = getLastArgIntValue( Args, OPT_fspell_checking_limit, DiagnosticOptions::DefaultSpellCheckingLimit, Diags); + Opts.SnippetLineLimit = getLastArgIntValue( + Args, OPT_fcaret_diagnostics_max_lines, + DiagnosticOptions::DefaultSnippetLineLimit, Diags); Opts.TabStop = getLastArgIntValue(Args, OPT_ftabstop, DiagnosticOptions::DefaultTabStop, Diags); if (Opts.TabStop == 0 || Opts.TabStop > DiagnosticOptions::MaxTabStop) { @@ -923,7 +1214,8 @@ } static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, - DiagnosticsEngine &Diags) { + DiagnosticsEngine &Diags, + bool &IsHeaderFile) { using namespace options; Opts.ProgramAction = frontend::ParseSyntaxOnly; if (const Arg *A = Args.getLastArg(OPT_Action_Group)) { @@ -933,6 +1225,7 @@ case OPT_ast_list: Opts.ProgramAction = frontend::ASTDeclList; break; case OPT_ast_dump: + case OPT_ast_dump_all: case OPT_ast_dump_lookups: Opts.ProgramAction = frontend::ASTDump; break; case OPT_ast_print: @@ -964,6 +1257,8 @@ Opts.ProgramAction = frontend::FixIt; break; case OPT_emit_module: Opts.ProgramAction = frontend::GenerateModule; break; + case OPT_emit_module_interface: + Opts.ProgramAction = frontend::GenerateModuleInterface; break; case OPT_emit_pch: Opts.ProgramAction = frontend::GeneratePCH; break; case OPT_emit_pth: @@ -1001,18 +1296,10 @@ Opts.Plugins.emplace_back(A->getValue(0)); Opts.ProgramAction = frontend::PluginAction; Opts.ActionName = A->getValue(); - - for (const Arg *AA : Args.filtered(OPT_plugin_arg)) - if (AA->getValue(0) == Opts.ActionName) - Opts.PluginArgs.emplace_back(AA->getValue(1)); } - Opts.AddPluginActions = Args.getAllArgValues(OPT_add_plugin); - Opts.AddPluginArgs.resize(Opts.AddPluginActions.size()); - for (int i = 0, e = Opts.AddPluginActions.size(); i != e; ++i) - for (const Arg *A : Args.filtered(OPT_plugin_arg)) - if (A->getValue(0) == Opts.AddPluginActions[i]) - Opts.AddPluginArgs[i].emplace_back(A->getValue(1)); + for (const Arg *AA : Args.filtered(OPT_plugin_arg)) + Opts.PluginArgs[AA->getValue(0)].emplace_back(AA->getValue(1)); for (const std::string &Arg : Args.getAllArgValues(OPT_ftest_module_file_extension_EQ)) { @@ -1030,8 +1317,8 @@ // Add the testing module file extension. Opts.ModuleFileExtensions.push_back( - new TestModuleFileExtension(BlockName, MajorVersion, MinorVersion, - Hashed, UserInfo)); + std::make_shared<TestModuleFileExtension>( + BlockName, MajorVersion, MinorVersion, Hashed, UserInfo)); } if (const Arg *A = Args.getLastArg(OPT_code_completion_at)) { @@ -1057,14 +1344,21 @@ Opts.FixAndRecompile = Args.hasArg(OPT_fixit_recompile); Opts.FixToTemporaries = Args.hasArg(OPT_fixit_to_temp); Opts.ASTDumpDecls = Args.hasArg(OPT_ast_dump); + Opts.ASTDumpAll = Args.hasArg(OPT_ast_dump_all); Opts.ASTDumpFilter = Args.getLastArgValue(OPT_ast_dump_filter); Opts.ASTDumpLookups = Args.hasArg(OPT_ast_dump_lookups); Opts.UseGlobalModuleIndex = !Args.hasArg(OPT_fno_modules_global_index); Opts.GenerateGlobalModuleIndex = Opts.UseGlobalModuleIndex; Opts.ModuleMapFiles = Args.getAllArgValues(OPT_fmodule_map_file); - Opts.ModuleFiles = Args.getAllArgValues(OPT_fmodule_file); + // Only the -fmodule-file=<file> form. + for (const Arg *A : Args.filtered(OPT_fmodule_file)) { + StringRef Val = A->getValue(); + if (Val.find('=') == StringRef::npos) + Opts.ModuleFiles.push_back(Val); + } Opts.ModulesEmbedFiles = Args.getAllArgValues(OPT_fmodules_embed_file_EQ); Opts.ModulesEmbedAllFiles = Args.hasArg(OPT_fmodules_embed_all_files); + Opts.IncludeTimestamps = !Args.hasArg(OPT_fno_pch_timestamp); Opts.CodeCompleteOpts.IncludeMacros = Args.hasArg(OPT_code_completion_macros); @@ -1079,6 +1373,8 @@ = Args.getLastArgValue(OPT_foverride_record_layout_EQ); Opts.AuxTriple = llvm::Triple::normalize(Args.getLastArgValue(OPT_aux_triple)); + Opts.FindPchSource = Args.getLastArgValue(OPT_find_pch_source_EQ); + Opts.StatsFile = Args.getLastArgValue(OPT_stats_file); if (const Arg *A = Args.getLastArg(OPT_arcmt_check, OPT_arcmt_modify, @@ -1142,37 +1438,57 @@ << "ARC migration" << "ObjC migration"; } - InputKind DashX = IK_None; + InputKind DashX(InputKind::Unknown); if (const Arg *A = Args.getLastArg(OPT_x)) { - DashX = llvm::StringSwitch<InputKind>(A->getValue()) - .Case("c", IK_C) - .Case("cl", IK_OpenCL) - .Case("cuda", IK_CUDA) - .Case("c++", IK_CXX) - .Case("objective-c", IK_ObjC) - .Case("objective-c++", IK_ObjCXX) - .Case("cpp-output", IK_PreprocessedC) - .Case("assembler-with-cpp", IK_Asm) - .Case("c++-cpp-output", IK_PreprocessedCXX) - .Case("cuda-cpp-output", IK_PreprocessedCuda) - .Case("objective-c-cpp-output", IK_PreprocessedObjC) - .Case("objc-cpp-output", IK_PreprocessedObjC) - .Case("objective-c++-cpp-output", IK_PreprocessedObjCXX) - .Case("objc++-cpp-output", IK_PreprocessedObjCXX) - .Case("c-header", IK_C) - .Case("cl-header", IK_OpenCL) - .Case("objective-c-header", IK_ObjC) - .Case("c++-header", IK_CXX) - .Case("objective-c++-header", IK_ObjCXX) - .Cases("ast", "pcm", IK_AST) - .Case("ir", IK_LLVM_IR) + StringRef XValue = A->getValue(); + + // Parse suffixes: '<lang>(-header|[-module-map][-cpp-output])'. + // FIXME: Supporting '<lang>-header-cpp-output' would be useful. + bool Preprocessed = XValue.consume_back("-cpp-output"); + bool ModuleMap = XValue.consume_back("-module-map"); + IsHeaderFile = + !Preprocessed && !ModuleMap && XValue.consume_back("-header"); + + // Principal languages. + DashX = llvm::StringSwitch<InputKind>(XValue) + .Case("c", InputKind::C) + .Case("cl", InputKind::OpenCL) + .Case("cuda", InputKind::CUDA) + .Case("c++", InputKind::CXX) + .Case("objective-c", InputKind::ObjC) + .Case("objective-c++", InputKind::ObjCXX) + .Case("renderscript", InputKind::RenderScript) #ifndef noCbC - .Case("cbc", IK_C) + .Case("cbc", InputKind::C) #endif - .Default(IK_None); - if (DashX == IK_None) + .Default(InputKind::Unknown); + + // "objc[++]-cpp-output" is an acceptable synonym for + // "objective-c[++]-cpp-output". + if (DashX.isUnknown() && Preprocessed && !IsHeaderFile && !ModuleMap) + DashX = llvm::StringSwitch<InputKind>(XValue) + .Case("objc", InputKind::ObjC) + .Case("objc++", InputKind::ObjCXX) + .Default(InputKind::Unknown); + + // Some special cases cannot be combined with suffixes. + if (DashX.isUnknown() && !Preprocessed && !ModuleMap && !IsHeaderFile) + DashX = llvm::StringSwitch<InputKind>(XValue) + .Case("cpp-output", InputKind(InputKind::C).getPreprocessed()) + .Case("assembler-with-cpp", InputKind::Asm) + .Cases("ast", "pcm", + InputKind(InputKind::Unknown, InputKind::Precompiled)) + .Case("ir", InputKind::LLVM_IR) + .Default(InputKind::Unknown); + + if (DashX.isUnknown()) Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << A->getValue(); + + if (Preprocessed) + DashX = DashX.getPreprocessed(); + if (ModuleMap) + DashX = DashX.withFormat(InputKind::ModuleMap); } // '-' is the default input if none is given. @@ -1182,13 +1498,22 @@ Inputs.push_back("-"); for (unsigned i = 0, e = Inputs.size(); i != e; ++i) { InputKind IK = DashX; - if (IK == IK_None) { + if (IK.isUnknown()) { IK = FrontendOptions::getInputKindForExtension( StringRef(Inputs[i]).rsplit('.').second); + // FIXME: Warn on this? + if (IK.isUnknown()) + IK = InputKind::C; // FIXME: Remove this hack. if (i == 0) DashX = IK; } + + // The -emit-module action implicitly takes a module map. + if (Opts.ProgramAction == frontend::GenerateModule && + IK.getFormat() == InputKind::Source) + IK = IK.withFormat(InputKind::ModuleMap); + Opts.Inputs.emplace_back(std::move(Inputs[i]), IK); } @@ -1213,7 +1538,8 @@ return P.str(); } -static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) { +static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args, + const std::string &WorkingDir) { using namespace options; Opts.Sysroot = Args.getLastArgValue(OPT_isysroot, "/"); Opts.Verbose = Args.hasArg(OPT_v); @@ -1223,9 +1549,31 @@ if (const Arg *A = Args.getLastArg(OPT_stdlib_EQ)) Opts.UseLibcxx = (strcmp(A->getValue(), "libc++") == 0); Opts.ResourceDir = Args.getLastArgValue(OPT_resource_dir); - Opts.ModuleCachePath = Args.getLastArgValue(OPT_fmodules_cache_path); + + // Canonicalize -fmodules-cache-path before storing it. + SmallString<128> P(Args.getLastArgValue(OPT_fmodules_cache_path)); + if (!(P.empty() || llvm::sys::path::is_absolute(P))) { + if (WorkingDir.empty()) + llvm::sys::fs::make_absolute(P); + else + llvm::sys::fs::make_absolute(WorkingDir, P); + } + llvm::sys::path::remove_dots(P); + Opts.ModuleCachePath = P.str(); + Opts.ModuleUserBuildPath = Args.getLastArgValue(OPT_fmodules_user_build_path); + // Only the -fmodule-file=<name>=<file> form. + for (const Arg *A : Args.filtered(OPT_fmodule_file)) { + StringRef Val = A->getValue(); + if (Val.find('=') != StringRef::npos) + Opts.PrebuiltModuleFiles.insert(Val.split('=')); + } + for (const Arg *A : Args.filtered(OPT_fprebuilt_module_path)) + Opts.AddPrebuiltModulePath(A->getValue()); Opts.DisableModuleHash = Args.hasArg(OPT_fdisable_module_hash); + Opts.ModulesHashContent = Args.hasArg(OPT_fmodules_hash_content); + Opts.ModulesValidateDiagnosticOptions = + !Args.hasArg(OPT_fmodules_disable_diagnostic_validation); Opts.ImplicitModuleMaps = Args.hasArg(OPT_fimplicit_module_maps); Opts.ModuleMapFileHomeIsCwd = Args.hasArg(OPT_fmodule_map_file_home_is_cwd); Opts.ModuleCachePruneInterval = @@ -1243,11 +1591,14 @@ for (const Arg *A : Args.filtered(OPT_fmodules_ignore_macro)) { StringRef MacroDef = A->getValue(); - Opts.ModulesIgnoreMacros.insert(MacroDef.split('=').first); + Opts.ModulesIgnoreMacros.insert( + llvm::CachedHashString(MacroDef.split('=').first)); } // Add -I..., -F..., and -index-header-map options in order. bool IsIndexHeaderMap = false; + bool IsSysrootSpecified = + Args.hasArg(OPT__sysroot_EQ) || Args.hasArg(OPT_isysroot); for (const Arg *A : Args.filtered(OPT_I, OPT_F, OPT_index_header_map)) { if (A->getOption().matches(OPT_index_header_map)) { // -index-header-map applies to the next -I or -F. @@ -1258,8 +1609,18 @@ frontend::IncludeDirGroup Group = IsIndexHeaderMap ? frontend::IndexHeaderMap : frontend::Angled; - Opts.AddPath(A->getValue(), Group, - /*IsFramework=*/A->getOption().matches(OPT_F), true); + bool IsFramework = A->getOption().matches(OPT_F); + std::string Path = A->getValue(); + + if (IsSysrootSpecified && !IsFramework && A->getValue()[0] == '=') { + SmallString<32> Buffer; + llvm::sys::path::append(Buffer, Opts.Sysroot, + llvm::StringRef(A->getValue()).substr(1)); + Path = Buffer.str(); + } + + Opts.AddPath(Path, Group, IsFramework, + /*IgnoreSysroot*/ true); IsIndexHeaderMap = false; } @@ -1284,6 +1645,9 @@ !A->getOption().matches(OPT_iwithsysroot)); for (const Arg *A : Args.filtered(OPT_iframework)) Opts.AddPath(A->getValue(), frontend::System, true, true); + for (const Arg *A : Args.filtered(OPT_iframeworkwithsysroot)) + Opts.AddPath(A->getValue(), frontend::System, /*IsFramework=*/true, + /*IgnoreSysRoot=*/false); // Add the paths for the various language specific isystem flags. for (const Arg *A : Args.filtered(OPT_c_isystem)) @@ -1315,45 +1679,55 @@ } void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK, + const llvm::Triple &T, + PreprocessorOptions &PPOpts, LangStandard::Kind LangStd) { // Set some properties which depend solely on the input kind; it would be nice // to move these to the language standard, and have the driver resolve the // input kind + language standard. - if (IK == IK_Asm) { + // + // FIXME: Perhaps a better model would be for a single source file to have + // multiple language standards (C / C++ std, ObjC std, OpenCL std, OpenMP std) + // simultaneously active? + if (IK.getLanguage() == InputKind::Asm) { Opts.AsmPreprocessor = 1; - } else if (IK == IK_ObjC || - IK == IK_ObjCXX || - IK == IK_PreprocessedObjC || - IK == IK_PreprocessedObjCXX) { + } else if (IK.isObjectiveC()) { Opts.ObjC1 = Opts.ObjC2 = 1; } if (LangStd == LangStandard::lang_unspecified) { // Based on the base language, pick one. - switch (IK) { - case IK_None: - case IK_AST: - case IK_LLVM_IR: + switch (IK.getLanguage()) { + case InputKind::Unknown: + case InputKind::LLVM_IR: llvm_unreachable("Invalid input kind!"); - case IK_OpenCL: - LangStd = LangStandard::lang_opencl; + case InputKind::OpenCL: + LangStd = LangStandard::lang_opencl10; break; - case IK_CUDA: - case IK_PreprocessedCuda: + case InputKind::CUDA: LangStd = LangStandard::lang_cuda; break; - case IK_Asm: - case IK_C: - case IK_PreprocessedC: - case IK_ObjC: - case IK_PreprocessedObjC: + case InputKind::Asm: + case InputKind::C: + // The PS4 uses C99 as the default C standard. + if (T.isPS4()) + LangStd = LangStandard::lang_gnu99; + else + LangStd = LangStandard::lang_gnu11; + break; + case InputKind::ObjC: LangStd = LangStandard::lang_gnu11; break; - case IK_CXX: - case IK_PreprocessedCXX: - case IK_ObjCXX: - case IK_PreprocessedObjCXX: - LangStd = LangStandard::lang_gnucxx98; + case InputKind::CXX: + case InputKind::ObjCXX: + // The PS4 uses C++11 as the default C++ standard. + if (T.isPS4()) + LangStd = LangStandard::lang_gnucxx11; + else + LangStd = LangStandard::lang_gnucxx98; + break; + case InputKind::RenderScript: + LangStd = LangStandard::lang_c99; break; } } @@ -1366,15 +1740,16 @@ Opts.CPlusPlus11 = Std.isCPlusPlus11(); Opts.CPlusPlus14 = Std.isCPlusPlus14(); Opts.CPlusPlus1z = Std.isCPlusPlus1z(); + Opts.CPlusPlus2a = Std.isCPlusPlus2a(); Opts.Digraphs = Std.hasDigraphs(); Opts.GNUMode = Std.isGNUMode(); - Opts.GNUInline = Std.isC89(); + Opts.GNUInline = !Opts.C99 && !Opts.CPlusPlus; Opts.HexFloats = Std.hasHexFloats(); Opts.ImplicitInt = Std.hasImplicitInt(); // Set OpenCL Version. - Opts.OpenCL = LangStd == LangStandard::lang_opencl || IK == IK_OpenCL; - if (LangStd == LangStandard::lang_opencl) + Opts.OpenCL = Std.isOpenCL(); + if (LangStd == LangStandard::lang_opencl10) Opts.OpenCLVersion = 100; else if (LangStd == LangStandard::lang_opencl11) Opts.OpenCLVersion = 110; @@ -1387,14 +1762,26 @@ if (Opts.OpenCL) { Opts.AltiVec = 0; Opts.ZVector = 0; - Opts.CXXOperatorNames = 1; Opts.LaxVectorConversions = 0; - Opts.DefaultFPContract = 1; + Opts.setDefaultFPContractMode(LangOptions::FPC_On); Opts.NativeHalfType = 1; + Opts.NativeHalfArgsAndReturns = 1; + // Include default header file for OpenCL. + if (Opts.IncludeDefaultHeader) { + PPOpts.Includes.push_back("opencl-c.h"); + } } - Opts.CUDA = IK == IK_CUDA || IK == IK_PreprocessedCuda || - LangStd == LangStandard::lang_cuda; + Opts.CUDA = IK.getLanguage() == InputKind::CUDA; + if (Opts.CUDA) + // Set default FP_CONTRACT to FAST. + Opts.setDefaultFPContractMode(LangOptions::FPC_Fast); + + Opts.RenderScript = IK.getLanguage() == InputKind::RenderScript; + if (Opts.RenderScript) { + Opts.NativeHalfType = 1; + Opts.NativeHalfArgsAndReturns = 1; + } // OpenCL and C++ both have bool, true, false keywords. Opts.Bool = Opts.OpenCL || Opts.CPlusPlus; @@ -1408,6 +1795,8 @@ Opts.GNUKeywords = Opts.GNUMode; Opts.CXXOperatorNames = Opts.CPlusPlus; + Opts.AlignedAllocation = Opts.CPlusPlus1z; + Opts.DollarIdents = !Opts.AsmPreprocessor; } @@ -1429,53 +1818,117 @@ return DefaultVisibility; } +/// Check if input file kind and language standard are compatible. +static bool IsInputCompatibleWithStandard(InputKind IK, + const LangStandard &S) { + switch (IK.getLanguage()) { + case InputKind::Unknown: + case InputKind::LLVM_IR: + llvm_unreachable("should not parse language flags for this input"); + + case InputKind::C: + case InputKind::ObjC: + case InputKind::RenderScript: + return S.getLanguage() == InputKind::C; + + case InputKind::OpenCL: + return S.getLanguage() == InputKind::OpenCL; + + case InputKind::CXX: + case InputKind::ObjCXX: + return S.getLanguage() == InputKind::CXX; + + case InputKind::CUDA: + // FIXME: What -std= values should be permitted for CUDA compilations? + return S.getLanguage() == InputKind::CUDA || + S.getLanguage() == InputKind::CXX; + + case InputKind::Asm: + // Accept (and ignore) all -std= values. + // FIXME: The -std= value is not ignored; it affects the tokenization + // and preprocessing rules if we're preprocessing this asm input. + return true; + } + + llvm_unreachable("unexpected input language"); +} + +/// Get language name for given input kind. +static const StringRef GetInputKindName(InputKind IK) { + switch (IK.getLanguage()) { + case InputKind::C: + return "C"; + case InputKind::ObjC: + return "Objective-C"; + case InputKind::CXX: + return "C++"; + case InputKind::ObjCXX: + return "Objective-C++"; + case InputKind::OpenCL: + return "OpenCL"; + case InputKind::CUDA: + return "CUDA"; + case InputKind::RenderScript: + return "RenderScript"; + + case InputKind::Asm: + return "Asm"; + case InputKind::LLVM_IR: + return "LLVM IR"; + + case InputKind::Unknown: + break; + } + llvm_unreachable("unknown input language"); +} + static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, + const TargetOptions &TargetOpts, + PreprocessorOptions &PPOpts, DiagnosticsEngine &Diags) { // FIXME: Cleanup per-file based stuff. LangStandard::Kind LangStd = LangStandard::lang_unspecified; if (const Arg *A = Args.getLastArg(OPT_std_EQ)) { LangStd = llvm::StringSwitch<LangStandard::Kind>(A->getValue()) -#define LANGSTANDARD(id, name, desc, features) \ +#define LANGSTANDARD(id, name, lang, desc, features) \ .Case(name, LangStandard::lang_##id) +#define LANGSTANDARD_ALIAS(id, alias) \ + .Case(alias, LangStandard::lang_##id) #include "clang/Frontend/LangStandards.def" .Default(LangStandard::lang_unspecified); - if (LangStd == LangStandard::lang_unspecified) + if (LangStd == LangStandard::lang_unspecified) { Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << A->getValue(); - else { + // Report supported standards with short description. + for (unsigned KindValue = 0; + KindValue != LangStandard::lang_unspecified; + ++KindValue) { + const LangStandard &Std = LangStandard::getLangStandardForKind( + static_cast<LangStandard::Kind>(KindValue)); + if (IsInputCompatibleWithStandard(IK, Std)) { + auto Diag = Diags.Report(diag::note_drv_use_standard); + Diag << Std.getName() << Std.getDescription(); + unsigned NumAliases = 0; +#define LANGSTANDARD(id, name, lang, desc, features) +#define LANGSTANDARD_ALIAS(id, alias) \ + if (KindValue == LangStandard::lang_##id) ++NumAliases; +#define LANGSTANDARD_ALIAS_DEPR(id, alias) +#include "clang/Frontend/LangStandards.def" + Diag << NumAliases; +#define LANGSTANDARD(id, name, lang, desc, features) +#define LANGSTANDARD_ALIAS(id, alias) \ + if (KindValue == LangStandard::lang_##id) Diag << alias; +#define LANGSTANDARD_ALIAS_DEPR(id, alias) +#include "clang/Frontend/LangStandards.def" + } + } + } else { // Valid standard, check to make sure language and standard are // compatible. const LangStandard &Std = LangStandard::getLangStandardForKind(LangStd); - switch (IK) { - case IK_C: - case IK_ObjC: - case IK_PreprocessedC: - case IK_PreprocessedObjC: - if (!(Std.isC89() || Std.isC99())) - Diags.Report(diag::err_drv_argument_not_allowed_with) - << A->getAsString(Args) << "C/ObjC"; - break; - case IK_CXX: - case IK_ObjCXX: - case IK_PreprocessedCXX: - case IK_PreprocessedObjCXX: - if (!Std.isCPlusPlus()) - Diags.Report(diag::err_drv_argument_not_allowed_with) - << A->getAsString(Args) << "C++/ObjC++"; - break; - case IK_OpenCL: - if (!Std.isC99()) - Diags.Report(diag::err_drv_argument_not_allowed_with) - << A->getAsString(Args) << "OpenCL"; - break; - case IK_CUDA: - case IK_PreprocessedCuda: - if (!Std.isCPlusPlus()) - Diags.Report(diag::err_drv_argument_not_allowed_with) - << A->getAsString(Args) << "CUDA"; - break; - default: - break; + if (!IsInputCompatibleWithStandard(IK, Std)) { + Diags.Report(diag::err_drv_argument_not_allowed_with) + << A->getAsString(Args) << GetInputKindName(IK); } } } @@ -1484,22 +1937,37 @@ // Override the -std option in this case. if (const Arg *A = Args.getLastArg(OPT_cl_std_EQ)) { LangStandard::Kind OpenCLLangStd - = llvm::StringSwitch<LangStandard::Kind>(A->getValue()) - .Case("CL", LangStandard::lang_opencl) - .Case("CL1.1", LangStandard::lang_opencl11) - .Case("CL1.2", LangStandard::lang_opencl12) - .Case("CL2.0", LangStandard::lang_opencl20) - .Default(LangStandard::lang_unspecified); + = llvm::StringSwitch<LangStandard::Kind>(A->getValue()) + .Cases("cl", "CL", LangStandard::lang_opencl10) + .Cases("cl1.1", "CL1.1", LangStandard::lang_opencl11) + .Cases("cl1.2", "CL1.2", LangStandard::lang_opencl12) + .Cases("cl2.0", "CL2.0", LangStandard::lang_opencl20) + .Default(LangStandard::lang_unspecified); if (OpenCLLangStd == LangStandard::lang_unspecified) { Diags.Report(diag::err_drv_invalid_value) - << A->getAsString(Args) << A->getValue(); + << A->getAsString(Args) << A->getValue(); } else LangStd = OpenCLLangStd; } - CompilerInvocation::setLangDefaults(Opts, IK, LangStd); + Opts.IncludeDefaultHeader = Args.hasArg(OPT_finclude_default_header); + + llvm::Triple T(TargetOpts.Triple); + CompilerInvocation::setLangDefaults(Opts, IK, T, PPOpts, LangStd); + + // -cl-strict-aliasing needs to emit diagnostic in the case where CL > 1.0. + // This option should be deprecated for CL > 1.0 because + // this option was added for compatibility with OpenCL 1.0. + if (Args.getLastArg(OPT_cl_strict_aliasing) + && Opts.OpenCLVersion > 100) { + std::string VerSpec = llvm::to_string(Opts.OpenCLVersion / 100) + + std::string(".") + + llvm::to_string((Opts.OpenCLVersion % 100) / 10); + Diags.Report(diag::warn_option_invalid_ocl_version) + << VerSpec << Args.getLastArg(OPT_cl_strict_aliasing)->getAsString(Args); + } // We abuse '-f[no-]gnu-keywords' to force overriding all GNU-extension // keywords. This behavior is provided by GCC's poorly named '-fasm' flag, @@ -1515,14 +1983,17 @@ if (Args.hasArg(OPT_fcuda_is_device)) Opts.CUDAIsDevice = 1; - if (Args.hasArg(OPT_fcuda_allow_host_calls_from_host_device)) - Opts.CUDAAllowHostCallsFromHostDevice = 1; + if (Args.hasArg(OPT_fcuda_allow_variadic_functions)) + Opts.CUDAAllowVariadicFunctions = 1; + + if (Args.hasArg(OPT_fno_cuda_host_device_constexpr)) + Opts.CUDAHostDeviceConstexpr = 0; - if (Args.hasArg(OPT_fcuda_disable_target_call_checks)) - Opts.CUDADisableTargetCallChecks = 1; + if (Opts.CUDAIsDevice && Args.hasArg(OPT_fcuda_flush_denormals_to_zero)) + Opts.CUDADeviceFlushDenormalsToZero = 1; - if (Args.hasArg(OPT_fcuda_target_overloads)) - Opts.CUDATargetOverloads = 1; + if (Opts.CUDAIsDevice && Args.hasArg(OPT_fcuda_approx_transcendentals)) + Opts.CUDADeviceApproxTranscendentals = 1; if (Opts.ObjC1) { if (Arg *arg = Args.getLastArg(OPT_fobjc_runtime_EQ)) { @@ -1576,8 +2047,8 @@ if (Args.hasArg(OPT_fgnu89_inline)) { if (Opts.CPlusPlus) - Diags.Report(diag::err_drv_argument_not_allowed_with) << "-fgnu89-inline" - << "C++/ObjC++"; + Diags.Report(diag::err_drv_argument_not_allowed_with) + << "-fgnu89-inline" << GetInputKindName(IK); else Opts.GNUInline = 1; } @@ -1594,9 +2065,6 @@ if (Args.hasArg(OPT_fno_constant_cfstrings)) Opts.NoConstantCFStrings = 1; - if (Args.hasArg(OPT_faltivec)) - Opts.AltiVec = 1; - if (Args.hasArg(OPT_fzvector)) Opts.ZVector = 1; @@ -1667,19 +2135,30 @@ Opts.ObjCExceptions = Args.hasArg(OPT_fobjc_exceptions); Opts.CXXExceptions = Args.hasArg(OPT_fcxx_exceptions); Opts.SjLjExceptions = Args.hasArg(OPT_fsjlj_exceptions); + Opts.ExternCNoUnwind = Args.hasArg(OPT_fexternc_nounwind); Opts.TraditionalCPP = Args.hasArg(OPT_traditional_cpp); - Opts.RTTI = !Args.hasArg(OPT_fno_rtti); + Opts.RTTI = Opts.CPlusPlus && !Args.hasArg(OPT_fno_rtti); Opts.RTTIData = Opts.RTTI && !Args.hasArg(OPT_fno_rtti_data); - Opts.Blocks = Args.hasArg(OPT_fblocks); + Opts.Blocks = Args.hasArg(OPT_fblocks) || (Opts.OpenCL + && Opts.OpenCLVersion >= 200); Opts.BlocksRuntimeOptional = Args.hasArg(OPT_fblocks_runtime_optional); - Opts.Coroutines = Args.hasArg(OPT_fcoroutines); - Opts.Modules = Args.hasArg(OPT_fmodules); + Opts.CoroutinesTS = Args.hasArg(OPT_fcoroutines_ts); + + // Enable [[]] attributes in C++11 by default. + Opts.DoubleSquareBracketAttributes = + Args.hasFlag(OPT_fdouble_square_bracket_attributes, + OPT_fno_double_square_bracket_attributes, Opts.CPlusPlus11); + + Opts.ModulesTS = Args.hasArg(OPT_fmodules_ts); + Opts.Modules = Args.hasArg(OPT_fmodules) || Opts.ModulesTS; Opts.ModulesStrictDeclUse = Args.hasArg(OPT_fmodules_strict_decluse); Opts.ModulesDeclUse = Args.hasArg(OPT_fmodules_decluse) || Opts.ModulesStrictDeclUse; Opts.ModulesLocalVisibility = - Args.hasArg(OPT_fmodules_local_submodule_visibility); + Args.hasArg(OPT_fmodules_local_submodule_visibility) || Opts.ModulesTS; + Opts.ModulesCodegen = Args.hasArg(OPT_fmodules_codegen); + Opts.ModulesDebugInfo = Args.hasArg(OPT_fmodules_debuginfo); Opts.ModulesSearchAll = Opts.Modules && !Args.hasArg(OPT_fno_modules_search_all) && Args.hasArg(OPT_fmodules_search_all); @@ -1687,22 +2166,45 @@ Opts.ImplicitModules = !Args.hasArg(OPT_fno_implicit_modules); Opts.CharIsSigned = Opts.OpenCL || !Args.hasArg(OPT_fno_signed_char); Opts.WChar = Opts.CPlusPlus && !Args.hasArg(OPT_fno_wchar); - Opts.ShortWChar = Args.hasFlag(OPT_fshort_wchar, OPT_fno_short_wchar, false); + if (const Arg *A = Args.getLastArg(OPT_fwchar_type_EQ)) { + Opts.WCharSize = llvm::StringSwitch<unsigned>(A->getValue()) + .Case("char", 1) + .Case("short", 2) + .Case("int", 4) + .Default(0); + if (Opts.WCharSize == 0) + Diags.Report(diag::err_fe_invalid_wchar_type) << A->getValue(); + } + Opts.WCharIsSigned = Args.hasFlag(OPT_fsigned_wchar, OPT_fno_signed_wchar, true); Opts.ShortEnums = Args.hasArg(OPT_fshort_enums); Opts.Freestanding = Args.hasArg(OPT_ffreestanding); Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding; if (!Opts.NoBuiltin) getAllNoBuiltinFuncValues(Args, Opts.NoBuiltinFuncs); Opts.NoMathBuiltin = Args.hasArg(OPT_fno_math_builtin); - Opts.AssumeSaneOperatorNew = !Args.hasArg(OPT_fno_assume_sane_operator_new); + Opts.RelaxedTemplateTemplateArgs = + Args.hasArg(OPT_frelaxed_template_template_args); Opts.SizedDeallocation = Args.hasArg(OPT_fsized_deallocation); + Opts.AlignedAllocation = + Args.hasFlag(OPT_faligned_allocation, OPT_fno_aligned_allocation, + Opts.AlignedAllocation); + Opts.AlignedAllocationUnavailable = + Opts.AlignedAllocation && Args.hasArg(OPT_aligned_alloc_unavailable); + Opts.NewAlignOverride = + getLastArgIntValue(Args, OPT_fnew_alignment_EQ, 0, Diags); + if (Opts.NewAlignOverride && !llvm::isPowerOf2_32(Opts.NewAlignOverride)) { + Arg *A = Args.getLastArg(OPT_fnew_alignment_EQ); + Diags.Report(diag::err_fe_invalid_alignment) << A->getAsString(Args) + << A->getValue(); + Opts.NewAlignOverride = 0; + } Opts.ConceptsTS = Args.hasArg(OPT_fconcepts_ts); Opts.HeinousExtensions = Args.hasArg(OPT_fheinous_gnu_extensions); Opts.AccessControl = !Args.hasArg(OPT_fno_access_control); Opts.ElideConstructors = !Args.hasArg(OPT_fno_elide_constructors); Opts.MathErrno = !Opts.OpenCL && Args.hasArg(OPT_fmath_errno); Opts.InstantiationDepth = - getLastArgIntValue(Args, OPT_ftemplate_depth, 256, Diags); + getLastArgIntValue(Args, OPT_ftemplate_depth, 1024, Diags); Opts.ArrowDepth = getLastArgIntValue(Args, OPT_foperator_arrow_depth, 256, Diags); Opts.ConstexprCallDepth = @@ -1723,8 +2225,9 @@ Opts.EmitAllDecls = Args.hasArg(OPT_femit_all_decls); Opts.PackStruct = getLastArgIntValue(Args, OPT_fpack_struct_EQ, 0, Diags); Opts.MaxTypeAlign = getLastArgIntValue(Args, OPT_fmax_type_align_EQ, 0, Diags); + Opts.AlignDouble = Args.hasArg(OPT_malign_double); Opts.PICLevel = getLastArgIntValue(Args, OPT_pic_level, 0, Diags); - Opts.PIELevel = getLastArgIntValue(Args, OPT_pie_level, 0, Diags); + Opts.PIE = Args.hasArg(OPT_pic_is_pie); Opts.Static = Args.hasArg(OPT_static_define); Opts.DumpRecordLayoutsSimple = Args.hasArg(OPT_fdump_record_layouts_simple); Opts.DumpRecordLayouts = Opts.DumpRecordLayoutsSimple @@ -1734,7 +2237,6 @@ Opts.NoBitFieldTypeAlign = Args.hasArg(OPT_fno_bitfield_type_align); Opts.SinglePrecisionConstants = Args.hasArg(OPT_cl_single_precision_constant); Opts.FastRelaxedMath = Args.hasArg(OPT_cl_fast_relaxed_math); - Opts.MRTD = Args.hasArg(OPT_mrtd); Opts.HexagonQdsp6Compat = Args.hasArg(OPT_mqdsp6_compat); Opts.FakeAddressSpaceMap = Args.hasArg(OPT_ffake_address_space_map); Opts.ParseUnknownAnytype = Args.hasArg(OPT_funknown_anytype); @@ -1742,39 +2244,30 @@ Opts.DebuggerCastResultToId = Args.hasArg(OPT_fdebugger_cast_result_to_id); Opts.DebuggerObjCLiteral = Args.hasArg(OPT_fdebugger_objc_literal); Opts.ApplePragmaPack = Args.hasArg(OPT_fapple_pragma_pack); - Opts.CurrentModule = Args.getLastArgValue(OPT_fmodule_name); + Opts.CurrentModule = Args.getLastArgValue(OPT_fmodule_name_EQ); Opts.AppExt = Args.hasArg(OPT_fapplication_extension); - Opts.ImplementationOfModule = - Args.getLastArgValue(OPT_fmodule_implementation_of); Opts.ModuleFeatures = Args.getAllArgValues(OPT_fmodule_feature); std::sort(Opts.ModuleFeatures.begin(), Opts.ModuleFeatures.end()); Opts.NativeHalfType |= Args.hasArg(OPT_fnative_half_type); - Opts.HalfArgsAndReturns = Args.hasArg(OPT_fallow_half_arguments_and_returns); + Opts.NativeHalfArgsAndReturns |= Args.hasArg(OPT_fnative_half_arguments_and_returns); + // Enable HalfArgsAndReturns if present in Args or if NativeHalfArgsAndReturns + // is enabled. + Opts.HalfArgsAndReturns = Args.hasArg(OPT_fallow_half_arguments_and_returns) + | Opts.NativeHalfArgsAndReturns; Opts.GNUAsm = !Args.hasArg(OPT_fno_gnu_inline_asm); // __declspec is enabled by default for the PS4 by the driver, and also // enabled for Microsoft Extensions or Borland Extensions, here. // // FIXME: __declspec is also currently enabled for CUDA, but isn't really a - // CUDA extension, however it is required for supporting cuda_builtin_vars.h, - // which uses __declspec(property). Once that has been rewritten in terms of - // something more generic, remove the Opts.CUDA term here. + // CUDA extension. However, it is required for supporting + // __clang_cuda_builtin_vars.h, which uses __declspec(property). Once that has + // been rewritten in terms of something more generic, remove the Opts.CUDA + // term here. Opts.DeclSpecKeyword = Args.hasFlag(OPT_fdeclspec, OPT_fno_declspec, (Opts.MicrosoftExt || Opts.Borland || Opts.CUDA)); - if (!Opts.CurrentModule.empty() && !Opts.ImplementationOfModule.empty() && - Opts.CurrentModule != Opts.ImplementationOfModule) { - Diags.Report(diag::err_conflicting_module_names) - << Opts.CurrentModule << Opts.ImplementationOfModule; - } - - // For now, we only support local submodule visibility in C++ (because we - // heavily depend on the ODR for merging redefinitions). - if (Opts.ModulesLocalVisibility && !Opts.CPlusPlus) - Diags.Report(diag::err_drv_argument_not_allowed_with) - << "-fmodules-local-submodule-visibility" << "C"; - if (Arg *A = Args.getLastArg(OPT_faddress_space_map_mangling_EQ)) { switch (llvm::StringSwitch<unsigned>(A->getValue()) .Case("target", LangOptions::ASMM_Target) @@ -1815,20 +2308,98 @@ Opts.setMSPointerToMemberRepresentationMethod(InheritanceModel); } + // Check for MS default calling conventions being specified. + if (Arg *A = Args.getLastArg(OPT_fdefault_calling_conv_EQ)) { + LangOptions::DefaultCallingConvention DefaultCC = + llvm::StringSwitch<LangOptions::DefaultCallingConvention>( + A->getValue()) + .Case("cdecl", LangOptions::DCC_CDecl) + .Case("fastcall", LangOptions::DCC_FastCall) + .Case("stdcall", LangOptions::DCC_StdCall) + .Case("vectorcall", LangOptions::DCC_VectorCall) + .Default(LangOptions::DCC_None); + if (DefaultCC == LangOptions::DCC_None) + Diags.Report(diag::err_drv_invalid_value) + << "-fdefault-calling-conv=" << A->getValue(); + + llvm::Triple T(TargetOpts.Triple); + llvm::Triple::ArchType Arch = T.getArch(); + bool emitError = (DefaultCC == LangOptions::DCC_FastCall || + DefaultCC == LangOptions::DCC_StdCall) && + Arch != llvm::Triple::x86; + emitError |= DefaultCC == LangOptions::DCC_VectorCall && + !(Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64); + if (emitError) + Diags.Report(diag::err_drv_argument_not_allowed_with) + << A->getSpelling() << T.getTriple(); + else + Opts.setDefaultCallingConv(DefaultCC); + } + + // -mrtd option + if (Arg *A = Args.getLastArg(OPT_mrtd)) { + if (Opts.getDefaultCallingConv() != LangOptions::DCC_None) + Diags.Report(diag::err_drv_argument_not_allowed_with) + << A->getSpelling() << "-fdefault-calling-conv"; + else { + llvm::Triple T(TargetOpts.Triple); + if (T.getArch() != llvm::Triple::x86) + Diags.Report(diag::err_drv_argument_not_allowed_with) + << A->getSpelling() << T.getTriple(); + else + Opts.setDefaultCallingConv(LangOptions::DCC_StdCall); + } + } + // Check if -fopenmp is specified. - Opts.OpenMP = Args.hasArg(options::OPT_fopenmp); + Opts.OpenMP = Args.hasArg(options::OPT_fopenmp) ? 1 : 0; Opts.OpenMPUseTLS = Opts.OpenMP && !Args.hasArg(options::OPT_fnoopenmp_use_tls); Opts.OpenMPIsDevice = Opts.OpenMP && Args.hasArg(options::OPT_fopenmp_is_device); + if (Opts.OpenMP) { + int Version = + getLastArgIntValue(Args, OPT_fopenmp_version_EQ, Opts.OpenMP, Diags); + if (Version != 0) + Opts.OpenMP = Version; + // Provide diagnostic when a given target is not expected to be an OpenMP + // device or host. + if (!Opts.OpenMPIsDevice) { + switch (T.getArch()) { + default: + break; + // Add unsupported host targets here: + case llvm::Triple::nvptx: + case llvm::Triple::nvptx64: + Diags.Report(clang::diag::err_drv_omp_host_target_not_supported) + << TargetOpts.Triple; + break; + } + } + } + + // Set the flag to prevent the implementation from emitting device exception + // handling code for those requiring so. + if (Opts.OpenMPIsDevice && T.isNVPTX()) { + Opts.Exceptions = 0; + Opts.CXXExceptions = 0; + } + // Get the OpenMP target triples if any. - if (Arg *A = Args.getLastArg(options::OPT_omptargets_EQ)) { + if (Arg *A = Args.getLastArg(options::OPT_fopenmp_targets_EQ)) { for (unsigned i = 0; i < A->getNumValues(); ++i) { llvm::Triple TT(A->getValue(i)); - if (TT.getArch() == llvm::Triple::UnknownArch) + if (TT.getArch() == llvm::Triple::UnknownArch || + !(TT.getArch() == llvm::Triple::ppc || + TT.getArch() == llvm::Triple::ppc64 || + TT.getArch() == llvm::Triple::ppc64le || + TT.getArch() == llvm::Triple::nvptx || + TT.getArch() == llvm::Triple::nvptx64 || + TT.getArch() == llvm::Triple::x86 || + TT.getArch() == llvm::Triple::x86_64)) Diags.Report(clang::diag::err_drv_invalid_omp_target) << A->getValue(i); else Opts.OMPTargetTriples.push_back(TT); @@ -1837,7 +2408,7 @@ // Get OpenMP host file path if any and report if a non existent file is // found - if (Arg *A = Args.getLastArg(options::OPT_omp_host_ir_file_path)) { + if (Arg *A = Args.getLastArg(options::OPT_fopenmp_host_ir_file_path)) { Opts.OMPHostIRFile = A->getValue(); if (!llvm::sys::fs::exists(Opts.OMPHostIRFile)) Diags.Report(clang::diag::err_drv_omp_host_ir_file_not_found) @@ -1858,7 +2429,12 @@ // This is the __NO_INLINE__ define, which just depends on things like the // optimization level and -fno-inline, not actually whether the backend has // inlining enabled. - Opts.NoInlineDefine = !Opt || Args.hasArg(OPT_fno_inline); + Opts.NoInlineDefine = !Opts.Optimize; + if (Arg *InlineArg = Args.getLastArg( + options::OPT_finline_functions, options::OPT_finline_hint_functions, + options::OPT_fno_inline_functions, options::OPT_fno_inline)) + if (InlineArg->getOption().matches(options::OPT_fno_inline)) + Opts.NoInlineDefine = true; Opts.FastMath = Args.hasArg(OPT_ffast_math) || Args.hasArg(OPT_cl_fast_relaxed_math); @@ -1869,6 +2445,18 @@ Args.hasArg(OPT_cl_unsafe_math_optimizations) || Args.hasArg(OPT_cl_fast_relaxed_math); + if (Arg *A = Args.getLastArg(OPT_ffp_contract)) { + StringRef Val = A->getValue(); + if (Val == "fast") + Opts.setDefaultFPContractMode(LangOptions::FPC_Fast); + else if (Val == "on") + Opts.setDefaultFPContractMode(LangOptions::FPC_On); + else if (Val == "off") + Opts.setDefaultFPContractMode(LangOptions::FPC_Off); + else + Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val; + } + Opts.RetainCommentsFromSystemHeaders = Args.hasArg(OPT_fretain_comments_from_system_headers); @@ -1891,11 +2479,66 @@ Opts.SanitizeAddressFieldPadding = getLastArgIntValue(Args, OPT_fsanitize_address_field_padding, 0, Diags); Opts.SanitizerBlacklistFiles = Args.getAllArgValues(OPT_fsanitize_blacklist); + + // -fxray-instrument + Opts.XRayInstrument = + Args.hasFlag(OPT_fxray_instrument, OPT_fnoxray_instrument, false); + + // -fxray-{always,never}-instrument= filenames. + Opts.XRayAlwaysInstrumentFiles = + Args.getAllArgValues(OPT_fxray_always_instrument); + Opts.XRayNeverInstrumentFiles = + Args.getAllArgValues(OPT_fxray_never_instrument); + + // -fallow-editor-placeholders + Opts.AllowEditorPlaceholders = Args.hasArg(OPT_fallow_editor_placeholders); +} + +static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) { + switch (Action) { + case frontend::ASTDeclList: + case frontend::ASTDump: + case frontend::ASTPrint: + case frontend::ASTView: + case frontend::EmitAssembly: + case frontend::EmitBC: + case frontend::EmitHTML: + case frontend::EmitLLVM: + case frontend::EmitLLVMOnly: + case frontend::EmitCodeGenOnly: + case frontend::EmitObj: + case frontend::FixIt: + case frontend::GenerateModule: + case frontend::GenerateModuleInterface: + case frontend::GeneratePCH: + case frontend::GeneratePTH: + case frontend::ParseSyntaxOnly: + case frontend::ModuleFileInfo: + case frontend::VerifyPCH: + case frontend::PluginAction: + case frontend::PrintDeclContext: + case frontend::RewriteObjC: + case frontend::RewriteTest: + case frontend::RunAnalysis: + case frontend::MigrateSource: + return false; + + case frontend::DumpRawTokens: + case frontend::DumpTokens: + case frontend::InitOnly: + case frontend::PrintPreamble: + case frontend::PrintPreprocessedInput: + case frontend::RewriteMacros: + case frontend::RunPreprocessorOnly: + return true; + } + llvm_unreachable("invalid frontend action"); } static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args, FileManager &FileMgr, - DiagnosticsEngine &Diags) { + DiagnosticsEngine &Diags, + frontend::ActionKind Action) { using namespace options; Opts.ImplicitPCHInclude = Args.getLastArgValue(OPT_include_pch); Opts.ImplicitPTHInclude = Args.getLastArgValue(OPT_include_pth); @@ -1906,6 +2549,7 @@ Opts.UsePredefines = !Args.hasArg(OPT_undef); Opts.DetailedRecord = Args.hasArg(OPT_detailed_preprocessing_record); Opts.DisablePCHValidation = Args.hasArg(OPT_fno_validate_pch); + Opts.AllowPCHWithCompilerErrors = Args.hasArg(OPT_fallow_pch_with_errors); Opts.DumpDeserializedPCHDecls = Args.hasArg(OPT_dump_deserialized_pch_decls); for (const Arg *A : Args.filtered(OPT_error_on_deserialized_pch_decl)) @@ -1944,10 +2588,6 @@ for (const Arg *A : Args.filtered(OPT_chain_include)) Opts.ChainedIncludes.emplace_back(A->getValue()); - // Include 'altivec.h' if -faltivec option present - if (Args.hasArg(OPT_faltivec)) - Opts.Includes.emplace_back("altivec.h"); - for (const Arg *A : Args.filtered(OPT_remap_file)) { std::pair<StringRef, StringRef> Split = StringRef(A->getValue()).split(';'); @@ -1971,6 +2611,12 @@ else Opts.ObjCXXARCStandardLibrary = (ObjCXXARCStandardLibraryKind)Library; } + + // Always avoid lexing editor placeholders when we're just running the + // preprocessor as we never want to emit the + // "editor placeholder in source file" error in PP only mode. + if (isStrictlyPreprocessorAction(Action)) + Opts.LexEditorPlaceholders = false; } static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts, @@ -1978,56 +2624,39 @@ frontend::ActionKind Action) { using namespace options; - switch (Action) { - case frontend::ASTDeclList: - case frontend::ASTDump: - case frontend::ASTPrint: - case frontend::ASTView: - case frontend::EmitAssembly: - case frontend::EmitBC: - case frontend::EmitHTML: - case frontend::EmitLLVM: - case frontend::EmitLLVMOnly: - case frontend::EmitCodeGenOnly: - case frontend::EmitObj: - case frontend::FixIt: - case frontend::GenerateModule: - case frontend::GeneratePCH: - case frontend::GeneratePTH: - case frontend::ParseSyntaxOnly: - case frontend::ModuleFileInfo: - case frontend::VerifyPCH: - case frontend::PluginAction: - case frontend::PrintDeclContext: - case frontend::RewriteObjC: - case frontend::RewriteTest: - case frontend::RunAnalysis: - case frontend::MigrateSource: + if (isStrictlyPreprocessorAction(Action)) + Opts.ShowCPP = !Args.hasArg(OPT_dM); + else Opts.ShowCPP = 0; - break; - - case frontend::DumpRawTokens: - case frontend::DumpTokens: - case frontend::InitOnly: - case frontend::PrintPreamble: - case frontend::PrintPreprocessedInput: - case frontend::RewriteMacros: - case frontend::RunPreprocessorOnly: - Opts.ShowCPP = !Args.hasArg(OPT_dM); - break; - } Opts.ShowComments = Args.hasArg(OPT_C); Opts.ShowLineMarkers = !Args.hasArg(OPT_P); Opts.ShowMacroComments = Args.hasArg(OPT_CC); Opts.ShowMacros = Args.hasArg(OPT_dM) || Args.hasArg(OPT_dD); + Opts.ShowIncludeDirectives = Args.hasArg(OPT_dI); Opts.RewriteIncludes = Args.hasArg(OPT_frewrite_includes); + Opts.RewriteImports = Args.hasArg(OPT_frewrite_imports); Opts.UseLineDirectives = Args.hasArg(OPT_fuse_line_directives); } -static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args) { +static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args, + DiagnosticsEngine &Diags) { using namespace options; Opts.ABI = Args.getLastArgValue(OPT_target_abi); + if (Arg *A = Args.getLastArg(OPT_meabi)) { + StringRef Value = A->getValue(); + llvm::EABI EABIVersion = llvm::StringSwitch<llvm::EABI>(Value) + .Case("default", llvm::EABI::Default) + .Case("4", llvm::EABI::EABI4) + .Case("5", llvm::EABI::EABI5) + .Case("gnu", llvm::EABI::GNU) + .Default(llvm::EABI::Unknown); + if (EABIVersion == llvm::EABI::Unknown) + Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) + << Value; + else + Opts.EABIVersion = EABIVersion; + } Opts.CPU = Args.getLastArgValue(OPT_target_cpu); Opts.FPMath = Args.getLastArgValue(OPT_mfpmath); Opts.FeaturesAsWritten = Args.getAllArgValues(OPT_target_feature); @@ -2037,6 +2666,7 @@ // Use the default target triple if unspecified. if (Opts.Triple.empty()) Opts.Triple = llvm::sys::getDefaultTargetTriple(); + Opts.OpenCLExtensionsAsWritten = Args.getAllArgValues(OPT_cl_ext_EQ); } bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res, @@ -2046,12 +2676,13 @@ bool Success = true; // Parse the arguments. - std::unique_ptr<OptTable> Opts(createDriverOptTable()); + std::unique_ptr<OptTable> Opts = createDriverOptTable(); const unsigned IncludedFlagsBitmask = options::CC1Option; unsigned MissingArgIndex, MissingArgCount; InputArgList Args = Opts->ParseArgs(llvm::makeArrayRef(ArgBegin, ArgEnd), MissingArgIndex, MissingArgCount, IncludedFlagsBitmask); + LangOptions &LangOpts = *Res.getLangOpts(); // Check for missing argument error. if (MissingArgCount) { @@ -2069,91 +2700,83 @@ Success &= ParseAnalyzerArgs(*Res.getAnalyzerOpts(), Args, Diags); Success &= ParseMigratorArgs(Res.getMigratorOpts(), Args); ParseDependencyOutputArgs(Res.getDependencyOutputOpts(), Args); - Success &= ParseDiagnosticArgs(Res.getDiagnosticOpts(), Args, &Diags); - ParseCommentArgs(Res.getLangOpts()->CommentOpts, Args); + Success &= + ParseDiagnosticArgs(Res.getDiagnosticOpts(), Args, &Diags, + false /*DefaultDiagColor*/, false /*DefaultShowOpt*/); + ParseCommentArgs(LangOpts.CommentOpts, Args); ParseFileSystemArgs(Res.getFileSystemOpts(), Args); // FIXME: We shouldn't have to pass the DashX option around here - InputKind DashX = ParseFrontendArgs(Res.getFrontendOpts(), Args, Diags); - ParseTargetArgs(Res.getTargetOpts(), Args); + InputKind DashX = ParseFrontendArgs(Res.getFrontendOpts(), Args, Diags, + LangOpts.IsHeaderFile); + ParseTargetArgs(Res.getTargetOpts(), Args, Diags); Success &= ParseCodeGenArgs(Res.getCodeGenOpts(), Args, DashX, Diags, Res.getTargetOpts()); - ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), Args); - if (DashX == IK_AST || DashX == IK_LLVM_IR) { + ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), Args, + Res.getFileSystemOpts().WorkingDir); + if (DashX.getFormat() == InputKind::Precompiled || + DashX.getLanguage() == InputKind::LLVM_IR) { // ObjCAAutoRefCount and Sanitize LangOpts are used to setup the // PassManager in BackendUtil.cpp. They need to be initializd no matter // what the input type is. if (Args.hasArg(OPT_fobjc_arc)) - Res.getLangOpts()->ObjCAutoRefCount = 1; + LangOpts.ObjCAutoRefCount = 1; + // PIClevel and PIELevel are needed during code generation and this should be + // set regardless of the input type. + LangOpts.PICLevel = getLastArgIntValue(Args, OPT_pic_level, 0, Diags); + LangOpts.PIE = Args.hasArg(OPT_pic_is_pie); parseSanitizerKinds("-fsanitize=", Args.getAllArgValues(OPT_fsanitize_EQ), - Diags, Res.getLangOpts()->Sanitize); + Diags, LangOpts.Sanitize); } else { // Other LangOpts are only initialzed when the input is not AST or LLVM IR. - ParseLangArgs(*Res.getLangOpts(), Args, DashX, Diags); + // FIXME: Should we really be calling this for an InputKind::Asm input? + ParseLangArgs(LangOpts, Args, DashX, Res.getTargetOpts(), + Res.getPreprocessorOpts(), Diags); if (Res.getFrontendOpts().ProgramAction == frontend::RewriteObjC) - Res.getLangOpts()->ObjCExceptions = 1; + LangOpts.ObjCExceptions = 1; + } + + if (LangOpts.CUDA) { + // During CUDA device-side compilation, the aux triple is the + // triple used for host compilation. + if (LangOpts.CUDAIsDevice) + Res.getTargetOpts().HostTriple = Res.getFrontendOpts().AuxTriple; } + + // Set the triple of the host for OpenMP device compile. + if (LangOpts.OpenMPIsDevice) + Res.getTargetOpts().HostTriple = Res.getFrontendOpts().AuxTriple; + + // FIXME: Override value name discarding when asan or msan is used because the + // backend passes depend on the name of the alloca in order to print out + // names. + Res.getCodeGenOpts().DiscardValueNames &= + !LangOpts.Sanitize.has(SanitizerKind::Address) && + !LangOpts.Sanitize.has(SanitizerKind::Memory); + // FIXME: ParsePreprocessorArgs uses the FileManager to read the contents of // PCH file and find the original header name. Remove the need to do that in // ParsePreprocessorArgs and remove the FileManager // parameters from the function and the "FileManager.h" #include. FileManager FileMgr(Res.getFileSystemOpts()); - ParsePreprocessorArgs(Res.getPreprocessorOpts(), Args, FileMgr, Diags); + ParsePreprocessorArgs(Res.getPreprocessorOpts(), Args, FileMgr, Diags, + Res.getFrontendOpts().ProgramAction); ParsePreprocessorOutputArgs(Res.getPreprocessorOutputOpts(), Args, Res.getFrontendOpts().ProgramAction); - return Success; -} -namespace { - - class ModuleSignature { - SmallVector<uint64_t, 16> Data; - unsigned CurBit; - uint64_t CurValue; - - public: - ModuleSignature() : CurBit(0), CurValue(0) { } - - void add(uint64_t Value, unsigned Bits); - void add(StringRef Value); - void flush(); - - llvm::APInt getAsInteger() const; - }; -} - -void ModuleSignature::add(uint64_t Value, unsigned int NumBits) { - CurValue |= Value << CurBit; - if (CurBit + NumBits < 64) { - CurBit += NumBits; - return; + // Turn on -Wspir-compat for SPIR target. + llvm::Triple T(Res.getTargetOpts().Triple); + auto Arch = T.getArch(); + if (Arch == llvm::Triple::spir || Arch == llvm::Triple::spir64) { + Res.getDiagnosticOpts().Warnings.push_back("spir-compat"); } - // Add the current word. - Data.push_back(CurValue); - - if (CurBit) - CurValue = Value >> (64-CurBit); - else - CurValue = 0; - CurBit = (CurBit+NumBits) & 63; -} - -void ModuleSignature::flush() { - if (CurBit == 0) - return; - - Data.push_back(CurValue); - CurBit = 0; - CurValue = 0; -} - -void ModuleSignature::add(StringRef Value) { - for (auto &c : Value) - add(c, 8); -} - -llvm::APInt ModuleSignature::getAsInteger() const { - return llvm::APInt(Data.size() * 64, Data); + // If sanitizer is enabled, disable OPT_ffine_grained_bitfield_accesses. + if (Res.getCodeGenOpts().FineGrainedBitfieldAccesses && + !Res.getLangOpts()->Sanitize.empty()) { + Res.getCodeGenOpts().FineGrainedBitfieldAccesses = false; + Diags.Report(diag::warn_drv_fine_grained_bitfield_accesses_ignored); + } + return Success; } std::string CompilerInvocation::getModuleHash() const { @@ -2200,7 +2823,8 @@ if (!hsOpts.ModulesIgnoreMacros.empty()) { // Check whether we're ignoring this macro. StringRef MacroDef = I->first; - if (hsOpts.ModulesIgnoreMacros.count(MacroDef.split('=').first)) + if (hsOpts.ModulesIgnoreMacros.count( + llvm::CachedHashString(MacroDef.split('=').first))) continue; } @@ -2214,7 +2838,8 @@ hsOpts.UseBuiltinIncludes, hsOpts.UseStandardSystemIncludes, hsOpts.UseStandardCXXIncludes, - hsOpts.UseLibcxx); + hsOpts.UseLibcxx, + hsOpts.ModulesValidateDiagnosticOptions); code = hash_combine(code, hsOpts.ResourceDir); // Extend the signature with the user build path. @@ -2222,32 +2847,16 @@ // Extend the signature with the module file extensions. const FrontendOptions &frontendOpts = getFrontendOpts(); - for (auto ext : frontendOpts.ModuleFileExtensions) { + for (const auto &ext : frontendOpts.ModuleFileExtensions) { code = ext->hashExtension(code); } - // Darwin-specific hack: if we have a sysroot, use the contents and - // modification time of - // $sysroot/System/Library/CoreServices/SystemVersion.plist - // as part of the module hash. - if (!hsOpts.Sysroot.empty()) { - SmallString<128> systemVersionFile; - systemVersionFile += hsOpts.Sysroot; - llvm::sys::path::append(systemVersionFile, "System"); - llvm::sys::path::append(systemVersionFile, "Library"); - llvm::sys::path::append(systemVersionFile, "CoreServices"); - llvm::sys::path::append(systemVersionFile, "SystemVersion.plist"); - - llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> buffer = - llvm::MemoryBuffer::getFile(systemVersionFile); - if (buffer) { - code = hash_combine(code, buffer.get()->getBuffer()); - - struct stat statBuf; - if (stat(systemVersionFile.c_str(), &statBuf) == 0) - code = hash_combine(code, statBuf.st_mtime); - } - } + // Extend the signature with the enabled sanitizers, if at least one is + // enabled. Sanitizers which cannot affect AST generation aren't hashed. + SanitizerSet SanHash = LangOpts->Sanitize; + SanHash.clear(getPPTransparentSanitizers()); + if (!SanHash.empty()) + code = hash_combine(code, SanHash.Mask); return llvm::APInt(64, code).toString(36, /*Signed=*/false); } @@ -2300,22 +2909,29 @@ IntrusiveRefCntPtr<vfs::FileSystem> createVFSFromCompilerInvocation(const CompilerInvocation &CI, DiagnosticsEngine &Diags) { - if (CI.getHeaderSearchOpts().VFSOverlayFiles.empty()) - return vfs::getRealFileSystem(); + return createVFSFromCompilerInvocation(CI, Diags, vfs::getRealFileSystem()); +} - IntrusiveRefCntPtr<vfs::OverlayFileSystem> - Overlay(new vfs::OverlayFileSystem(vfs::getRealFileSystem())); +IntrusiveRefCntPtr<vfs::FileSystem> +createVFSFromCompilerInvocation(const CompilerInvocation &CI, + DiagnosticsEngine &Diags, + IntrusiveRefCntPtr<vfs::FileSystem> BaseFS) { + if (CI.getHeaderSearchOpts().VFSOverlayFiles.empty()) + return BaseFS; + + IntrusiveRefCntPtr<vfs::OverlayFileSystem> Overlay( + new vfs::OverlayFileSystem(BaseFS)); // earlier vfs files are on the bottom for (const std::string &File : CI.getHeaderSearchOpts().VFSOverlayFiles) { llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buffer = - llvm::MemoryBuffer::getFile(File); + BaseFS->getBufferForFile(File); if (!Buffer) { Diags.Report(diag::err_missing_vfs_overlay_file) << File; return IntrusiveRefCntPtr<vfs::FileSystem>(); } - IntrusiveRefCntPtr<vfs::FileSystem> FS = - vfs::getVFSFromYAML(std::move(Buffer.get()), /*DiagHandler*/ nullptr); + IntrusiveRefCntPtr<vfs::FileSystem> FS = vfs::getVFSFromYAML( + std::move(Buffer.get()), /*DiagHandler*/ nullptr, File); if (!FS.get()) { Diags.Report(diag::err_invalid_vfs_overlay) << File; return IntrusiveRefCntPtr<vfs::FileSystem>();
--- a/tools/clang/lib/Parse/ParseCbC.cpp Wed Dec 06 14:37:17 2017 +0900 +++ b/tools/clang/lib/Parse/ParseCbC.cpp Tue Dec 12 19:42:58 2017 +0900 @@ -369,7 +369,7 @@ QualType R = Actions.getCurFunctionDecl()->getReturnType(); // copy a type TypeSourceInfo *TInfo = Actions.Context.CreateTypeSourceInfo(R); // copy a type infomation Scope *S = getCurScope(); - LookupResult Previous(Actions, NameInfo, Actions.LookupOrdinaryName, Actions.ForRedeclaration); + LookupResult Previous(Actions, NameInfo, Actions.LookupOrdinaryName, Actions.ForVisibleRedeclaration); bool IsLinkageLookup = false; bool CreateBuiltins = false; @@ -432,7 +432,8 @@ StmtResult IfRes; ParseScope IfScope(this, Scope::DeclScope | Scope::ControlScope, true/* C99 or CXX */); ExprResult CondExp; - Decl *CondVar = 0; + StmtResult InitStmt; + Sema::ConditionResult Cond; CondExp = LookupNameAndBuildExpr(CreateIdentifierInfo("__builtin_setjmp", Loc)); ExprVector ArgExprs; @@ -443,9 +444,8 @@ ArgExprs.push_back(__envExprRes.get()); CondExp = Actions.ActOnCallExpr(getCurScope(), CondExp.get(), Loc, ArgExprs, Loc, 0); - CondExp = Actions.ActOnBooleanCondition(getCurScope(), Loc, CondExp.get()); + CondExp = Actions.CheckBooleanCondition(Loc, CondExp.get()); - FullExprArg FullCondExp(Actions.MakeFullExpr(CondExp.get(), Loc)); ParseScope InnerScope(this, Scope::DeclScope,false); SourceLocation InnerStatementTrailingElseLoc; @@ -464,7 +464,8 @@ InnerScope.Exit(); IfScope.Exit(); StmtResult ElseStmt; - IfRes = Actions.ActOnIfStmt(Loc, FullCondExp, CondVar, ThenStmt.get(),Loc, ElseStmt.get()); + bool IsConstexpr = false; + IfRes = Actions.ActOnIfStmt(Loc, IsConstexpr, InitStmt.get(), Cond, ThenStmt.get(),Loc, ElseStmt.get()); return IfRes; } @@ -503,7 +504,7 @@ IdentifierInfo *Name = CreateIdentifierInfo(__CBC_STRUCT_NAME, Loc); // Check previous definition. If the __CbC_env has been already defined, we have not to create again. - LookupResult Previous(Actions, Name, Loc, Actions.LookupTagName, Actions.ForRedeclaration); + LookupResult Previous(Actions, Name, Loc, Actions.LookupTagName, Actions.ForVisibleRedeclaration); if(Actions.LookupName(Previous, getCurScope())) return; @@ -530,7 +531,7 @@ TagOrTempResult = Actions.ActOnTag(getCurScope(), TagType, Sema::TUK_Definition, Loc, SDS.getTypeSpecScope(), Name, Loc, attrs.getList(), AS, SDS.getModulePrivateSpecLoc(), TParams, Owned, IsDependent, - SourceLocation(), false, clang::TypeResult(), false); + SourceLocation(), false, clang::TypeResult(), false, false); Decl *TagDecl = TagOrTempResult.get(); PrettyDeclStackTraceEntry CrashInfo(Actions, TagDecl, Loc, "parsing struct/union body"); @@ -864,7 +865,7 @@ DS->getModulePrivateSpecLoc(), TParams, Owned, IsDependent, SourceLocation(), false, - clang::TypeResult(), false); + clang::TypeResult(), false, false); isInvalid = DS->SetTypeSpecType(T, Loc, Loc, PrevSpec, DiagID, TagOrTempResult.get(), Owned, Policy); } else if (T == DeclSpec::TST_typename) { @@ -904,7 +905,7 @@ /// If not, include it. void Parser::CheckTheSjHeader(){ SourceLocation Loc = Tok.getLocation(); - LookupResult R(Actions, CreateIdentifierInfo("setjmp", Loc), Loc, Actions.LookupOrdinaryName, Actions.ForRedeclaration); + LookupResult R(Actions, CreateIdentifierInfo("setjmp", Loc), Loc, Actions.LookupOrdinaryName, Actions.ForVisibleRedeclaration); if (!Actions.LookupName(R, getCurScope())){ // look up the setjmp if (PP.IncludeHeader(Tok, "setjmp.h")) ConsumeToken();
--- a/tools/clang/lib/Sema/DeclSpec.cpp Wed Dec 06 14:37:17 2017 +0900 +++ b/tools/clang/lib/Sema/DeclSpec.cpp Tue Dec 12 19:42:58 2017 +0900 @@ -15,10 +15,10 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/Expr.h" +#include "clang/AST/LocInfoType.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/TargetInfo.h" -#include "clang/Sema/LocInfoType.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Sema.h" #include "clang/Sema/SemaDiagnostic.h" @@ -173,6 +173,8 @@ unsigned NumExceptions, Expr *NoexceptExpr, CachedTokens *ExceptionSpecTokens, + ArrayRef<NamedDecl*> + DeclsInPrototype, SourceLocation LocalRangeBegin, SourceLocation LocalRangeEnd, Declarator &TheDeclarator, @@ -204,7 +206,7 @@ I.Fun.ExceptionSpecType = ESpecType; I.Fun.ExceptionSpecLocBeg = ESpecRange.getBegin().getRawEncoding(); I.Fun.ExceptionSpecLocEnd = ESpecRange.getEnd().getRawEncoding(); - I.Fun.NumExceptions = 0; + I.Fun.NumExceptionsOrDecls = 0; I.Fun.Exceptions = nullptr; I.Fun.NoexceptExpr = nullptr; I.Fun.HasTrailingReturnType = TrailingReturnType.isUsable() || @@ -220,16 +222,18 @@ // parameter list there (in an effort to avoid new/delete traffic). If it // is already used (consider a function returning a function pointer) or too // small (function with too many parameters), go to the heap. - if (!TheDeclarator.InlineParamsUsed && + if (!TheDeclarator.InlineStorageUsed && NumParams <= llvm::array_lengthof(TheDeclarator.InlineParams)) { I.Fun.Params = TheDeclarator.InlineParams; + new (I.Fun.Params) ParamInfo[NumParams]; I.Fun.DeleteParams = false; - TheDeclarator.InlineParamsUsed = true; + TheDeclarator.InlineStorageUsed = true; } else { I.Fun.Params = new DeclaratorChunk::ParamInfo[NumParams]; I.Fun.DeleteParams = true; } - memcpy(I.Fun.Params, Params, sizeof(Params[0]) * NumParams); + for (unsigned i = 0; i < NumParams; i++) + I.Fun.Params[i] = std::move(Params[i]); } // Check what exception specification information we should actually store. @@ -238,7 +242,7 @@ case EST_Dynamic: // new[] an exception array if needed if (NumExceptions) { - I.Fun.NumExceptions = NumExceptions; + I.Fun.NumExceptionsOrDecls = NumExceptions; I.Fun.Exceptions = new DeclaratorChunk::TypeAndRange[NumExceptions]; for (unsigned i = 0; i != NumExceptions; ++i) { I.Fun.Exceptions[i].Ty = Exceptions[i]; @@ -255,9 +259,52 @@ I.Fun.ExceptionSpecTokens = ExceptionSpecTokens; break; } + + if (!DeclsInPrototype.empty()) { + assert(ESpecType == EST_None && NumExceptions == 0 && + "cannot have exception specifiers and decls in prototype"); + I.Fun.NumExceptionsOrDecls = DeclsInPrototype.size(); + // Copy the array of decls into stable heap storage. + I.Fun.DeclsInPrototype = new NamedDecl *[DeclsInPrototype.size()]; + for (size_t J = 0; J < DeclsInPrototype.size(); ++J) + I.Fun.DeclsInPrototype[J] = DeclsInPrototype[J]; + } + return I; } +void Declarator::setDecompositionBindings( + SourceLocation LSquareLoc, + ArrayRef<DecompositionDeclarator::Binding> Bindings, + SourceLocation RSquareLoc) { + assert(!hasName() && "declarator given multiple names!"); + + BindingGroup.LSquareLoc = LSquareLoc; + BindingGroup.RSquareLoc = RSquareLoc; + BindingGroup.NumBindings = Bindings.size(); + Range.setEnd(RSquareLoc); + + // We're now past the identifier. + SetIdentifier(nullptr, LSquareLoc); + Name.EndLocation = RSquareLoc; + + // Allocate storage for bindings and stash them away. + if (Bindings.size()) { + if (!InlineStorageUsed && + Bindings.size() <= llvm::array_lengthof(InlineBindings)) { + BindingGroup.Bindings = InlineBindings; + BindingGroup.DeleteBindings = false; + InlineStorageUsed = true; + } else { + BindingGroup.Bindings = + new DecompositionDeclarator::Binding[Bindings.size()]; + BindingGroup.DeleteBindings = true; + } + std::uninitialized_copy(Bindings.begin(), Bindings.end(), + BindingGroup.Bindings); + } +} + bool Declarator::isDeclarationOfFunction() const { for (unsigned i = 0, i_end = DeclTypeInfo.size(); i < i_end; ++i) { switch (DeclTypeInfo[i].Kind) { @@ -289,6 +336,8 @@ case TST_decimal32: case TST_decimal64: case TST_double: + case TST_Float16: + case TST_float128: case TST_enum: case TST_error: case TST_float: @@ -305,6 +354,8 @@ #ifndef noCbC case TST___code: #endif +#define GENERIC_IMAGE_TYPE(ImgType, Id) case TST_##ImgType##_t: +#include "clang/Basic/OpenCLImageTypes.def" return false; case TST_decltype_auto: @@ -458,6 +509,8 @@ case DeclSpec::TST_half: return "half"; case DeclSpec::TST_float: return "float"; case DeclSpec::TST_double: return "double"; + case DeclSpec::TST_float16: return "_Float16"; + case DeclSpec::TST_float128: return "__float128"; case DeclSpec::TST_bool: return Policy.Bool ? "bool" : "_Bool"; case DeclSpec::TST_decimal32: return "_Decimal32"; case DeclSpec::TST_decimal64: return "_Decimal64"; @@ -477,6 +530,10 @@ case DeclSpec::TST_underlyingType: return "__underlying_type"; case DeclSpec::TST_unknown_anytype: return "__unknown_anytype"; case DeclSpec::TST_atomic: return "_Atomic"; +#define GENERIC_IMAGE_TYPE(ImgType, Id) \ + case DeclSpec::TST_##ImgType##_t: \ + return #ImgType "_t"; +#include "clang/Basic/OpenCLImageTypes.def" case DeclSpec::TST_error: return "(error)"; #ifndef noCbC case DeclSpec::TST___code: return "__code"; @@ -492,6 +549,7 @@ case DeclSpec::TQ_restrict: return "restrict"; case DeclSpec::TQ_volatile: return "volatile"; case DeclSpec::TQ_atomic: return "_Atomic"; + case DeclSpec::TQ_unaligned: return "__unaligned"; } llvm_unreachable("Unknown typespec!"); } @@ -508,7 +566,7 @@ // OpenCL v1.2 s6.8 changes this to "The auto and register storage-class // specifiers are not supported." if (S.getLangOpts().OpenCL && - !S.getOpenCLOptions().cl_clang_storage_class_specifiers) { + !S.getOpenCLOptions().isEnabled("cl_clang_storage_class_specifiers")) { switch (SC) { case SCS_extern: case SCS_private_extern: @@ -575,14 +633,16 @@ const char *&PrevSpec, unsigned &DiagID, const PrintingPolicy &Policy) { - // Overwrite TSWLoc only if TypeSpecWidth was unspecified, so that + // Overwrite TSWRange.Begin only if TypeSpecWidth was unspecified, so that // for 'long long' we will keep the source location of the first 'long'. if (TypeSpecWidth == TSW_unspecified) - TSWLoc = Loc; + TSWRange.setBegin(Loc); // Allow turning long -> long long. else if (W != TSW_longlong || TypeSpecWidth != TSW_long) return BadSpecifier(W, (TSW)TypeSpecWidth, PrevSpec, DiagID); TypeSpecWidth = W; + // Remember location of the last 'long' + TSWRange.setEnd(Loc); return false; } @@ -793,6 +853,7 @@ case TQ_const: TQ_constLoc = Loc; return false; case TQ_restrict: TQ_restrictLoc = Loc; return false; case TQ_volatile: TQ_volatileLoc = Loc; return false; + case TQ_unaligned: TQ_unalignedLoc = Loc; return false; case TQ_atomic: TQ_atomicLoc = Loc; return false; } @@ -959,11 +1020,11 @@ TypeSpecSign != TSS_unspecified || TypeAltiVecVector || TypeAltiVecPixel || TypeAltiVecBool || TypeQualifiers)) { - const unsigned NumLocs = 8; + const unsigned NumLocs = 9; SourceLocation ExtraLocs[NumLocs] = { - TSWLoc, TSCLoc, TSSLoc, AltiVecLoc, - TQ_constLoc, TQ_restrictLoc, TQ_volatileLoc, TQ_atomicLoc - }; + TSWRange.getBegin(), TSCLoc, TSSLoc, + AltiVecLoc, TQ_constLoc, TQ_restrictLoc, + TQ_volatileLoc, TQ_atomicLoc, TQ_unalignedLoc}; FixItHint Hints[NumLocs]; SourceLocation FirstLoc; for (unsigned I = 0; I != NumLocs; ++I) { @@ -1005,8 +1066,8 @@ // Only 'short' and 'long long' are valid with vector bool. (PIM 2.1) if ((TypeSpecWidth != TSW_unspecified) && (TypeSpecWidth != TSW_short) && (TypeSpecWidth != TSW_longlong)) - S.Diag(TSWLoc, diag::err_invalid_vector_bool_decl_spec) - << getSpecifierName((TSW)TypeSpecWidth); + S.Diag(TSWRange.getBegin(), diag::err_invalid_vector_bool_decl_spec) + << getSpecifierName((TSW)TypeSpecWidth); // vector bool long long requires VSX support or ZVector. if ((TypeSpecWidth == TSW_longlong) && @@ -1023,21 +1084,25 @@ // vector long double and vector long long double are never allowed. // vector double is OK for Power7 and later, and ZVector. if (TypeSpecWidth == TSW_long || TypeSpecWidth == TSW_longlong) - S.Diag(TSWLoc, diag::err_invalid_vector_long_double_decl_spec); + S.Diag(TSWRange.getBegin(), + diag::err_invalid_vector_long_double_decl_spec); else if (!S.Context.getTargetInfo().hasFeature("vsx") && !S.getLangOpts().ZVector) S.Diag(TSTLoc, diag::err_invalid_vector_double_decl_spec); } else if (TypeSpecType == TST_float) { - // vector float is unsupported for ZVector. - if (S.getLangOpts().ZVector) + // vector float is unsupported for ZVector unless we have the + // vector-enhancements facility 1 (ISA revision 12). + if (S.getLangOpts().ZVector && + !S.Context.getTargetInfo().hasFeature("arch12")) S.Diag(TSTLoc, diag::err_invalid_vector_float_decl_spec); } else if (TypeSpecWidth == TSW_long) { // vector long is unsupported for ZVector and deprecated for AltiVec. if (S.getLangOpts().ZVector) - S.Diag(TSWLoc, diag::err_invalid_vector_long_decl_spec); + S.Diag(TSWRange.getBegin(), diag::err_invalid_vector_long_decl_spec); else - S.Diag(TSWLoc, diag::warn_vector_long_decl_spec_combination) - << getSpecifierName((TST)TypeSpecType, Policy); + S.Diag(TSWRange.getBegin(), + diag::warn_vector_long_decl_spec_combination) + << getSpecifierName((TST)TypeSpecType, Policy); } if (TypeAltiVecPixel) { @@ -1070,8 +1135,8 @@ if (TypeSpecType == TST_unspecified) TypeSpecType = TST_int; // short -> short int, long long -> long long int. else if (TypeSpecType != TST_int) { - S.Diag(TSWLoc, diag::err_invalid_width_spec) << (int)TypeSpecWidth - << getSpecifierName((TST)TypeSpecType, Policy); + S.Diag(TSWRange.getBegin(), diag::err_invalid_width_spec) + << (int)TypeSpecWidth << getSpecifierName((TST)TypeSpecType, Policy); TypeSpecType = TST_int; TypeSpecOwned = false; } @@ -1080,8 +1145,8 @@ if (TypeSpecType == TST_unspecified) TypeSpecType = TST_int; // long -> long int. else if (TypeSpecType != TST_int && TypeSpecType != TST_double) { - S.Diag(TSWLoc, diag::err_invalid_width_spec) << (int)TypeSpecWidth - << getSpecifierName((TST)TypeSpecType, Policy); + S.Diag(TSWRange.getBegin(), diag::err_invalid_width_spec) + << (int)TypeSpecWidth << getSpecifierName((TST)TypeSpecType, Policy); TypeSpecType = TST_int; TypeSpecOwned = false; } @@ -1263,6 +1328,7 @@ switch (VS) { default: llvm_unreachable("Unknown specifier!"); case VS_Override: VS_overrideLoc = Loc; break; + case VS_GNU_Final: case VS_Sealed: case VS_Final: VS_finalLoc = Loc; break; } @@ -1275,6 +1341,7 @@ default: llvm_unreachable("Unknown specifier"); case VS_Override: return "override"; case VS_Final: return "final"; + case VS_GNU_Final: return "__final"; case VS_Sealed: return "sealed"; } }